New upstream version 1.9.24
Emmanuel Bourg
5 years ago
8 | 8 | <groupId>com.ning</groupId> |
9 | 9 | <artifactId>async-http-client</artifactId> |
10 | 10 | <name>Asynchronous Http Client</name> |
11 | <version>1.9.23</version> | |
11 | <version>1.9.24</version> | |
12 | 12 | <packaging>jar</packaging> |
13 | 13 | <description> |
14 | 14 | Async Http Client library purpose is to allow Java applications to easily execute HTTP requests and |
16 | 16 | |
17 | 17 | import com.ning.http.client.cookie.Cookie; |
18 | 18 | import com.ning.http.client.multipart.Part; |
19 | import com.ning.http.util.QueryComputer; | |
19 | import com.ning.http.util.UriEncoder; | |
20 | 20 | |
21 | 21 | import java.io.InputStream; |
22 | 22 | import java.util.Collection; |
42 | 42 | super(RequestBuilder.class, method, disableUrlEncoding); |
43 | 43 | } |
44 | 44 | |
45 | public RequestBuilder(String method, QueryComputer queryComputer) { | |
46 | super(RequestBuilder.class, method, queryComputer); | |
45 | public RequestBuilder(String method, UriEncoder uriEncoder) { | |
46 | super(RequestBuilder.class, method, uriEncoder); | |
47 | 47 | } |
48 | 48 | |
49 | 49 | public RequestBuilder(Request prototype) { |
50 | 50 | super(RequestBuilder.class, prototype); |
51 | 51 | } |
52 | 52 | |
53 | public RequestBuilder(Request prototype, QueryComputer queryComputer) { | |
54 | super(RequestBuilder.class, prototype, queryComputer); | |
53 | public RequestBuilder(Request prototype, UriEncoder uriEncoder) { | |
54 | super(RequestBuilder.class, prototype, uriEncoder); | |
55 | 55 | } |
56 | 56 | |
57 | 57 | // Note: For now we keep the delegates in place even though they are not needed |
23 | 23 | import com.ning.http.client.multipart.Part; |
24 | 24 | import com.ning.http.client.uri.Uri; |
25 | 25 | import com.ning.http.util.AsyncHttpProviderUtils; |
26 | import com.ning.http.util.QueryComputer; | |
26 | import com.ning.http.util.UriEncoder; | |
27 | 27 | |
28 | 28 | import java.io.File; |
29 | 29 | import java.io.InputStream; |
277 | 277 | |
278 | 278 | private final Class<T> derived; |
279 | 279 | protected final RequestImpl request; |
280 | protected QueryComputer queryComputer; | |
280 | protected UriEncoder uriEncoder; | |
281 | 281 | protected List<Param> queryParams; |
282 | 282 | protected SignatureCalculator signatureCalculator; |
283 | 283 | |
284 | 284 | protected RequestBuilderBase(Class<T> derived, String method, boolean disableUrlEncoding) { |
285 | this(derived, method, QueryComputer.queryComputer(disableUrlEncoding)); | |
286 | } | |
287 | ||
288 | protected RequestBuilderBase(Class<T> derived, String method, QueryComputer queryComputer) { | |
285 | this(derived, method, UriEncoder.uriEncoder(disableUrlEncoding)); | |
286 | } | |
287 | ||
288 | protected RequestBuilderBase(Class<T> derived, String method, UriEncoder uriEncoder) { | |
289 | 289 | this.derived = derived; |
290 | 290 | request = new RequestImpl(); |
291 | 291 | request.method = method; |
292 | this.queryComputer = queryComputer; | |
292 | this.uriEncoder = uriEncoder; | |
293 | 293 | } |
294 | 294 | |
295 | 295 | protected RequestBuilderBase(Class<T> derived, Request prototype) { |
296 | this(derived, prototype, QueryComputer.URL_ENCODING_ENABLED_QUERY_COMPUTER); | |
297 | } | |
298 | ||
299 | protected RequestBuilderBase(Class<T> derived, Request prototype, QueryComputer queryComputer) { | |
296 | this(derived, prototype, UriEncoder.FIXING); | |
297 | } | |
298 | ||
299 | protected RequestBuilderBase(Class<T> derived, Request prototype, UriEncoder uriEncoder) { | |
300 | 300 | this.derived = derived; |
301 | 301 | request = new RequestImpl(prototype); |
302 | this.queryComputer = queryComputer; | |
302 | this.uriEncoder = uriEncoder; | |
303 | 303 | } |
304 | 304 | |
305 | 305 | public T setUrl(String url) { |
626 | 626 | |
627 | 627 | private void computeFinalUri() { |
628 | 628 | |
629 | if (request.uri == null) { | |
629 | Uri originalUri = request.uri; | |
630 | if (originalUri == null) { | |
630 | 631 | logger.debug("setUrl hasn't been invoked. Using {}", DEFAULT_REQUEST_URL); |
631 | 632 | request.uri = DEFAULT_REQUEST_URL; |
632 | 633 | } |
633 | 634 | |
634 | AsyncHttpProviderUtils.validateSupportedScheme(request.uri); | |
635 | ||
636 | String newQuery = queryComputer.computeFullQueryString(request.uri.getQuery(), queryParams); | |
637 | request.uri = request.uri.withNewQuery(newQuery); | |
635 | AsyncHttpProviderUtils.validateSupportedScheme(originalUri); | |
636 | ||
637 | request.uri = uriEncoder.encode(originalUri, queryParams); | |
638 | 638 | } |
639 | 639 | |
640 | 640 | public Request build() { |
14 | 14 | import static com.ning.http.util.MiscUtils.isNonEmpty; |
15 | 15 | import static java.nio.charset.StandardCharsets.US_ASCII; |
16 | 16 | |
17 | import com.ning.http.client.FluentStringsMap; | |
18 | 17 | import com.ning.http.client.Param; |
19 | 18 | |
20 | 19 | import java.io.IOException; |
21 | 20 | import java.io.OutputStream; |
22 | 21 | import java.nio.charset.Charset; |
22 | import java.util.ArrayList; | |
23 | import java.util.List; | |
23 | 24 | |
24 | 25 | public abstract class PartBase implements Part { |
25 | 26 | |
56 | 57 | /** |
57 | 58 | * Additional part headers |
58 | 59 | */ |
59 | private FluentStringsMap customHeaders; | |
60 | private List<Param> customHeaders; | |
60 | 61 | |
61 | 62 | public PartBase(String name, String contentType, Charset charset, String contentId) { |
62 | 63 | this(name, contentType, charset, contentId, null); |
130 | 131 | |
131 | 132 | protected void visitCustomHeaders(PartVisitor visitor) throws IOException { |
132 | 133 | if (isNonEmpty(customHeaders)) { |
133 | for (Param param: customHeaders.toParams()) { | |
134 | for (Param param: customHeaders) { | |
134 | 135 | visitor.withBytes(CRLF_BYTES); |
135 | 136 | visitor.withBytes(param.getName().getBytes(US_ASCII)); |
136 | 137 | visitor.withBytes(param.getValue().getBytes(US_ASCII)); |
254 | 255 | |
255 | 256 | public void addCustomHeader(String name, String value) { |
256 | 257 | if (customHeaders == null) { |
257 | customHeaders = new FluentStringsMap(); | |
258 | } | |
259 | customHeaders.add(name, value); | |
258 | customHeaders = new ArrayList<Param>(2); | |
259 | } | |
260 | customHeaders.add(new Param(name, value)); | |
261 | } | |
262 | ||
263 | public void setCustomHeaders(List<Param> customHeaders) { | |
264 | this.customHeaders = customHeaders; | |
260 | 265 | } |
261 | 266 | } |
229 | 229 | } |
230 | 230 | |
231 | 231 | public OAuthParameterSet add(String key, String value) { |
232 | Parameter p = new Parameter(UTF8UrlEncoder.encode(key), UTF8UrlEncoder.encode(value)); | |
232 | Parameter p = new Parameter(UTF8UrlEncoder.encodeQueryElement(key), UTF8UrlEncoder.encodeQueryElement(value)); | |
233 | 233 | allParameters.add(p); |
234 | 234 | return this; |
235 | 235 | } |
+4
-1
64 | 64 | |
65 | 65 | private void writeRequest(Channel channel) { |
66 | 66 | |
67 | LOGGER.debug("Request using non cached Channel '{}':\n{}\n", channel, future.getNettyRequest().getHttpRequest()); | |
67 | LOGGER.debug("Using non-cached Channel {} for {} '{}'", | |
68 | channel, | |
69 | future.getNettyRequest().getHttpRequest().getMethod(), | |
70 | future.getNettyRequest().getHttpRequest().getUri()); | |
68 | 71 | |
69 | 72 | Channels.setAttribute(channel, future); |
70 | 73 |
204 | 204 | future.setState(NettyResponseFuture.STATE.POOLED); |
205 | 205 | future.attachChannel(channel, false); |
206 | 206 | |
207 | LOGGER.debug("Using cached Channel {}\n for request \n{}\n", channel, future.getNettyRequest().getHttpRequest()); | |
207 | LOGGER.debug("Using cached Channel {} for {} '{}'", | |
208 | channel, | |
209 | future.getNettyRequest().getHttpRequest().getMethod(), | |
210 | future.getNettyRequest().getHttpRequest().getUri()); | |
208 | 211 | |
209 | 212 | if (Channels.isChannelValid(channel)) { |
210 | 213 | Channels.setAttribute(channel, future); |
85 | 85 | } |
86 | 86 | } |
87 | 87 | |
88 | @SuppressWarnings("resource") | |
89 | 88 | public final static InputStream contentToInputStream(List<HttpResponseBodyPart> bodyParts) throws UnsupportedEncodingException { |
90 | 89 | return bodyParts.isEmpty() ? new ByteArrayInputStream(EMPTY_BYTE_ARRAY) : new HttpResponseBodyPartsInputStream(bodyParts); |
91 | 90 | } |
191 | 190 | } |
192 | 191 | sb.append('&'); |
193 | 192 | } |
194 | ||
195 | public static void encodeAndAppendQueryParam(final StringBuilder sb, final CharSequence name, final CharSequence value) { | |
196 | UTF8UrlEncoder.encodeAndAppendQueryElement(sb, name); | |
197 | if (value != null) { | |
198 | sb.append('='); | |
199 | UTF8UrlEncoder.encodeAndAppendQueryElement(sb, value); | |
200 | } | |
201 | sb.append('&'); | |
202 | } | |
203 | 193 | } |
0 | /* | |
1 | * Copyright (c) 2014 AsyncHttpClient Project. All rights reserved. | |
2 | * | |
3 | * This program is licensed to you under the Apache License Version 2.0, | |
4 | * and you may not use this file except in compliance with the Apache License Version 2.0. | |
5 | * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | |
6 | * | |
7 | * Unless required by applicable law or agreed to in writing, | |
8 | * software distributed under the Apache License Version 2.0 is distributed on an | |
9 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
10 | * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | |
11 | */ | |
12 | package com.ning.http.util; | |
13 | ||
14 | import static com.ning.http.util.MiscUtils.isNonEmpty; | |
15 | import static com.ning.http.util.AsyncHttpProviderUtils.encodeAndAppendQueryParam; | |
16 | import static com.ning.http.util.UTF8UrlEncoder.encodeAndAppendQuery; | |
17 | import com.ning.http.client.Param; | |
18 | ||
19 | import java.util.List; | |
20 | ||
21 | public enum QueryComputer { | |
22 | ||
23 | URL_ENCODING_ENABLED_QUERY_COMPUTER { | |
24 | ||
25 | private final void encodeAndAppendQueryParams(final StringBuilder sb, final List<Param> queryParams) { | |
26 | for (Param param : queryParams) | |
27 | encodeAndAppendQueryParam(sb, param.getName(), param.getValue()); | |
28 | } | |
29 | ||
30 | protected final String withQueryWithParams(final String query, final List<Param> queryParams) { | |
31 | // concatenate encoded query + encoded query params | |
32 | StringBuilder sb = StringUtils.stringBuilder(); | |
33 | encodeAndAppendQuery(sb, query); | |
34 | sb.append('&'); | |
35 | encodeAndAppendQueryParams(sb, queryParams); | |
36 | sb.setLength(sb.length() - 1); | |
37 | return sb.toString(); | |
38 | } | |
39 | ||
40 | protected final String withQueryWithoutParams(final String query) { | |
41 | // encode query | |
42 | StringBuilder sb = StringUtils.stringBuilder(); | |
43 | encodeAndAppendQuery(sb, query); | |
44 | return sb.toString(); | |
45 | } | |
46 | ||
47 | protected final String withoutQueryWithParams(final List<Param> queryParams) { | |
48 | // concatenate encoded query params | |
49 | StringBuilder sb = StringUtils.stringBuilder(); | |
50 | encodeAndAppendQueryParams(sb, queryParams); | |
51 | sb.setLength(sb.length() - 1); | |
52 | return sb.toString(); | |
53 | } | |
54 | }, // | |
55 | ||
56 | URL_ENCODING_DISABLED_QUERY_COMPUTER { | |
57 | ||
58 | private final void appendRawQueryParam(StringBuilder sb, String name, String value) { | |
59 | sb.append(name); | |
60 | if (value != null) | |
61 | sb.append('=').append(value); | |
62 | sb.append('&'); | |
63 | } | |
64 | ||
65 | private final void appendRawQueryParams(final StringBuilder sb, final List<Param> queryParams) { | |
66 | for (Param param : queryParams) | |
67 | appendRawQueryParam(sb, param.getName(), param.getValue()); | |
68 | } | |
69 | ||
70 | protected final String withQueryWithParams(final String query, final List<Param> queryParams) { | |
71 | // concatenate raw query + raw query params | |
72 | StringBuilder sb = StringUtils.stringBuilder(); | |
73 | sb.append(query); | |
74 | appendRawQueryParams(sb, queryParams); | |
75 | sb.setLength(sb.length() - 1); | |
76 | return sb.toString(); | |
77 | } | |
78 | ||
79 | protected final String withQueryWithoutParams(final String query) { | |
80 | // return raw query as is | |
81 | return query; | |
82 | } | |
83 | ||
84 | protected final String withoutQueryWithParams(final List<Param> queryParams) { | |
85 | // concatenate raw queryParams | |
86 | StringBuilder sb = StringUtils.stringBuilder(); | |
87 | appendRawQueryParams(sb, queryParams); | |
88 | sb.setLength(sb.length() - 1); | |
89 | return sb.toString(); | |
90 | } | |
91 | }; | |
92 | ||
93 | public static QueryComputer queryComputer(boolean disableUrlEncoding) { | |
94 | return disableUrlEncoding ? URL_ENCODING_DISABLED_QUERY_COMPUTER : URL_ENCODING_ENABLED_QUERY_COMPUTER; | |
95 | } | |
96 | ||
97 | protected abstract String withQueryWithParams(final String query, final List<Param> queryParams); | |
98 | ||
99 | protected abstract String withQueryWithoutParams(final String query); | |
100 | ||
101 | protected abstract String withoutQueryWithParams(final List<Param> queryParams); | |
102 | ||
103 | private final String withQuery(final String query, final List<Param> queryParams) { | |
104 | return isNonEmpty(queryParams) ? withQueryWithParams(query, queryParams) : withQueryWithoutParams(query); | |
105 | } | |
106 | ||
107 | private final String withoutQuery(final List<Param> queryParams) { | |
108 | return isNonEmpty(queryParams) ? withoutQueryWithParams(queryParams) : null; | |
109 | } | |
110 | ||
111 | public final String computeFullQueryString(final String query, final List<Param> queryParams) { | |
112 | return isNonEmpty(query) ? withQuery(query, queryParams) : withoutQuery(queryParams); | |
113 | } | |
114 | } |
28 | 28 | */ |
29 | 29 | public final static BitSet RFC3986_UNRESERVED_CHARS = new BitSet(256); |
30 | 30 | public final static BitSet RFC3986_RESERVED_CHARS = new BitSet(256); |
31 | public final static BitSet RFC3986_SUBDELIM_CHARS = new BitSet(256); | |
32 | public final static BitSet BUILT_PATH_UNTOUCHED_CHARS = new BitSet(256); | |
31 | 33 | public final static BitSet BUILT_QUERY_UNTOUCHED_CHARS = new BitSet(256); |
32 | 34 | // http://www.w3.org/TR/html5/forms.html#application/x-www-form-urlencoded-encoding-algorithm |
33 | 35 | public final static BitSet FORM_URL_ENCODED_SAFE_CHARS = new BitSet(256); |
50 | 52 | RFC3986_UNRESERVED_CHARS.set('_'); |
51 | 53 | RFC3986_UNRESERVED_CHARS.set('~'); |
52 | 54 | |
55 | RFC3986_SUBDELIM_CHARS.set('!'); | |
56 | RFC3986_SUBDELIM_CHARS.set('$'); | |
57 | RFC3986_SUBDELIM_CHARS.set('&'); | |
58 | RFC3986_SUBDELIM_CHARS.set('\''); | |
59 | RFC3986_SUBDELIM_CHARS.set('('); | |
60 | RFC3986_SUBDELIM_CHARS.set(')'); | |
61 | RFC3986_SUBDELIM_CHARS.set('*'); | |
62 | RFC3986_SUBDELIM_CHARS.set('+'); | |
63 | RFC3986_SUBDELIM_CHARS.set(','); | |
64 | RFC3986_SUBDELIM_CHARS.set(';'); | |
65 | RFC3986_SUBDELIM_CHARS.set('='); | |
66 | ||
53 | 67 | FORM_URL_ENCODED_SAFE_CHARS.set('-'); |
54 | 68 | FORM_URL_ENCODED_SAFE_CHARS.set('.'); |
55 | 69 | FORM_URL_ENCODED_SAFE_CHARS.set('_'); |
73 | 87 | RFC3986_RESERVED_CHARS.set('#'); |
74 | 88 | RFC3986_RESERVED_CHARS.set('['); |
75 | 89 | RFC3986_RESERVED_CHARS.set(']'); |
76 | ||
90 | ||
91 | BUILT_PATH_UNTOUCHED_CHARS.or(RFC3986_UNRESERVED_CHARS); | |
92 | BUILT_PATH_UNTOUCHED_CHARS.set('%'); | |
93 | BUILT_PATH_UNTOUCHED_CHARS.or(RFC3986_SUBDELIM_CHARS); | |
94 | BUILT_PATH_UNTOUCHED_CHARS.set(':'); | |
95 | BUILT_PATH_UNTOUCHED_CHARS.set('@'); | |
96 | BUILT_PATH_UNTOUCHED_CHARS.set('/'); | |
97 | ||
77 | 98 | BUILT_QUERY_UNTOUCHED_CHARS.or(RFC3986_UNRESERVED_CHARS); |
78 | 99 | BUILT_QUERY_UNTOUCHED_CHARS.or(RFC3986_RESERVED_CHARS); |
79 | 100 | BUILT_QUERY_UNTOUCHED_CHARS.set('%'); |
84 | 105 | private UTF8UrlEncoder() { |
85 | 106 | } |
86 | 107 | |
87 | public static String encode(String input) { | |
88 | StringBuilder sb = new StringBuilder(input.length() + 16); | |
108 | public static String encodePath(String input) { | |
109 | StringBuilder sb = new StringBuilder(input.length() + 6); | |
110 | appendEncoded(sb, input, BUILT_PATH_UNTOUCHED_CHARS, false); | |
111 | return sb.toString(); | |
112 | } | |
113 | ||
114 | public static StringBuilder encodeAndAppendQuery(StringBuilder sb, String query) { | |
115 | return appendEncoded(sb, query, BUILT_QUERY_UNTOUCHED_CHARS, false); | |
116 | } | |
117 | ||
118 | public static String encodeQueryElement(String input) { | |
119 | StringBuilder sb = new StringBuilder(input.length() + 6); | |
89 | 120 | encodeAndAppendQueryElement(sb, input); |
90 | 121 | return sb.toString(); |
91 | } | |
92 | ||
93 | public static StringBuilder encodeAndAppendQuery(StringBuilder sb, String query) { | |
94 | return appendEncoded(sb, query, BUILT_QUERY_UNTOUCHED_CHARS, false); | |
95 | 122 | } |
96 | 123 | |
97 | 124 | public static StringBuilder encodeAndAppendQueryElement(StringBuilder sb, CharSequence input) { |
0 | /* | |
1 | * Copyright (c) 2014 AsyncHttpClient Project. All rights reserved. | |
2 | * | |
3 | * This program is licensed to you under the Apache License Version 2.0, | |
4 | * and you may not use this file except in compliance with the Apache License Version 2.0. | |
5 | * You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0. | |
6 | * | |
7 | * Unless required by applicable law or agreed to in writing, | |
8 | * software distributed under the Apache License Version 2.0 is distributed on an | |
9 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
10 | * See the Apache License Version 2.0 for the specific language governing permissions and limitations there under. | |
11 | */ | |
12 | package com.ning.http.util; | |
13 | ||
14 | import static com.ning.http.util.MiscUtils.isNonEmpty; | |
15 | import static com.ning.http.util.UTF8UrlEncoder.encodeAndAppendQuery; | |
16 | ||
17 | import com.ning.http.client.Param; | |
18 | import com.ning.http.client.uri.Uri; | |
19 | ||
20 | import java.util.List; | |
21 | ||
22 | public enum UriEncoder { | |
23 | ||
24 | FIXING { | |
25 | ||
26 | public String encodePath(String path) { | |
27 | return UTF8UrlEncoder.encodePath(path); | |
28 | } | |
29 | ||
30 | private void encodeAndAppendQueryParam(final StringBuilder sb, final CharSequence name, final CharSequence value) { | |
31 | UTF8UrlEncoder.encodeAndAppendQueryElement(sb, name); | |
32 | if (value != null) { | |
33 | sb.append('='); | |
34 | UTF8UrlEncoder.encodeAndAppendQueryElement(sb, value); | |
35 | } | |
36 | sb.append('&'); | |
37 | } | |
38 | ||
39 | private void encodeAndAppendQueryParams(final StringBuilder sb, final List<Param> queryParams) { | |
40 | for (Param param : queryParams) | |
41 | encodeAndAppendQueryParam(sb, param.getName(), param.getValue()); | |
42 | } | |
43 | ||
44 | protected String withQueryWithParams(final String query, final List<Param> queryParams) { | |
45 | // concatenate encoded query + encoded query params | |
46 | StringBuilder sb = StringUtils.stringBuilder(); | |
47 | encodeAndAppendQuery(sb, query); | |
48 | sb.append('&'); | |
49 | encodeAndAppendQueryParams(sb, queryParams); | |
50 | sb.setLength(sb.length() - 1); | |
51 | return sb.toString(); | |
52 | } | |
53 | ||
54 | protected String withQueryWithoutParams(final String query) { | |
55 | // encode query | |
56 | StringBuilder sb = StringUtils.stringBuilder(); | |
57 | encodeAndAppendQuery(sb, query); | |
58 | return sb.toString(); | |
59 | } | |
60 | ||
61 | protected String withoutQueryWithParams(final List<Param> queryParams) { | |
62 | // concatenate encoded query params | |
63 | StringBuilder sb = StringUtils.stringBuilder(); | |
64 | encodeAndAppendQueryParams(sb, queryParams); | |
65 | sb.setLength(sb.length() - 1); | |
66 | return sb.toString(); | |
67 | } | |
68 | }, // | |
69 | ||
70 | RAW { | |
71 | ||
72 | public String encodePath(String path) { | |
73 | return path; | |
74 | } | |
75 | ||
76 | private void appendRawQueryParam(StringBuilder sb, String name, String value) { | |
77 | sb.append(name); | |
78 | if (value != null) | |
79 | sb.append('=').append(value); | |
80 | sb.append('&'); | |
81 | } | |
82 | ||
83 | private void appendRawQueryParams(final StringBuilder sb, final List<Param> queryParams) { | |
84 | for (Param param : queryParams) | |
85 | appendRawQueryParam(sb, param.getName(), param.getValue()); | |
86 | } | |
87 | ||
88 | protected String withQueryWithParams(final String query, final List<Param> queryParams) { | |
89 | // concatenate raw query + raw query params | |
90 | StringBuilder sb = StringUtils.stringBuilder(); | |
91 | sb.append(query); | |
92 | appendRawQueryParams(sb, queryParams); | |
93 | sb.setLength(sb.length() - 1); | |
94 | return sb.toString(); | |
95 | } | |
96 | ||
97 | protected String withQueryWithoutParams(final String query) { | |
98 | // return raw query as is | |
99 | return query; | |
100 | } | |
101 | ||
102 | protected String withoutQueryWithParams(final List<Param> queryParams) { | |
103 | // concatenate raw queryParams | |
104 | StringBuilder sb = StringUtils.stringBuilder(); | |
105 | appendRawQueryParams(sb, queryParams); | |
106 | sb.setLength(sb.length() - 1); | |
107 | return sb.toString(); | |
108 | } | |
109 | }; | |
110 | ||
111 | public static UriEncoder uriEncoder(boolean disableUrlEncoding) { | |
112 | return disableUrlEncoding ? RAW : FIXING; | |
113 | } | |
114 | ||
115 | protected abstract String withQueryWithParams(final String query, final List<Param> queryParams); | |
116 | ||
117 | protected abstract String withQueryWithoutParams(final String query); | |
118 | ||
119 | protected abstract String withoutQueryWithParams(final List<Param> queryParams); | |
120 | ||
121 | private final String withQuery(final String query, final List<Param> queryParams) { | |
122 | return isNonEmpty(queryParams) ? withQueryWithParams(query, queryParams) : withQueryWithoutParams(query); | |
123 | } | |
124 | ||
125 | private final String withoutQuery(final List<Param> queryParams) { | |
126 | return isNonEmpty(queryParams) ? withoutQueryWithParams(queryParams) : null; | |
127 | } | |
128 | ||
129 | public Uri encode(Uri uri, List<Param> queryParams) { | |
130 | String newPath = encodePath(uri.getPath()); | |
131 | String newQuery = encodeQuery(uri.getQuery(), queryParams); | |
132 | return new Uri(uri.getScheme(),// | |
133 | uri.getUserInfo(),// | |
134 | uri.getHost(),// | |
135 | uri.getPort(),// | |
136 | newPath,// | |
137 | newQuery); | |
138 | } | |
139 | ||
140 | protected abstract String encodePath(String path); | |
141 | ||
142 | private final String encodeQuery(final String query, final List<Param> queryParams) { | |
143 | return isNonEmpty(query) ? withQuery(query, queryParams) : withoutQuery(queryParams); | |
144 | } | |
145 | } |
21 | 21 | |
22 | 22 | @Test(groups = "fast") |
23 | 23 | public void testBasics() { |
24 | Assert.assertEquals(UTF8UrlEncoder.encode("foobar"), "foobar"); | |
25 | Assert.assertEquals(UTF8UrlEncoder.encode("a&b"), "a%26b"); | |
26 | Assert.assertEquals(UTF8UrlEncoder.encode("a+b"), "a%2Bb"); | |
24 | Assert.assertEquals(UTF8UrlEncoder.encodeQueryElement("foobar"), "foobar"); | |
25 | Assert.assertEquals(UTF8UrlEncoder.encodeQueryElement("a&b"), "a%26b"); | |
26 | Assert.assertEquals(UTF8UrlEncoder.encodeQueryElement("a+b"), "a%2Bb"); | |
27 | 27 | } |
28 | 28 | |
29 | 29 | @Test(groups = "fast") |
30 | 30 | public void testNonBmp() { |
31 | 31 | // Plane 1 |
32 | Assert.assertEquals(UTF8UrlEncoder.encode("\uD83D\uDCA9"), "%F0%9F%92%A9"); | |
32 | Assert.assertEquals(UTF8UrlEncoder.encodeQueryElement("\uD83D\uDCA9"), "%F0%9F%92%A9"); | |
33 | 33 | // Plane 2 |
34 | Assert.assertEquals(UTF8UrlEncoder.encode("\ud84c\uddc8 \ud84f\udfef"), "%F0%A3%87%88%20%F0%A3%BF%AF"); | |
34 | Assert.assertEquals(UTF8UrlEncoder.encodeQueryElement("\ud84c\uddc8 \ud84f\udfef"), "%F0%A3%87%88%20%F0%A3%BF%AF"); | |
35 | 35 | // Plane 15 |
36 | Assert.assertEquals(UTF8UrlEncoder.encode("\udb80\udc01"), "%F3%B0%80%81"); | |
36 | Assert.assertEquals(UTF8UrlEncoder.encodeQueryElement("\udb80\udc01"), "%F3%B0%80%81"); | |
37 | 37 | } |
38 | 38 | |
39 | 39 | @Test(groups = "fast") |