I am struggling to write test(s) for the following post method (junit/mockito)
POST method
public JSONObject post(final String url, final Map<String, File> fileMap) {
final OkHttpClient client = OkHttpClientSingleton.getInstance();
final MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
try {
for (final Map.Entry entry : fileMap.entrySet()) {
final String contentType;
final Path path = Paths.get(((File) entry.getValue()).getAbsolutePath());
contentType = Files.probeContentType(path);
final MediaType FILE_MEDIA_TYPE = MediaType.parse(contentType);
builder.addFormDataPart((String) entry.getKey(), ((File) entry.getValue()).getName(), RequestBody.create(FILE_MEDIA_TYPE, (File) entry.getValue()));
}
} catch (final IOException e) {
e.printStackTrace();
return null;
}
final RequestBody requestBody = builder.build();
final Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
return execute(client, request);
}
and the execute method looks like:
private JSONObject execute(final OkHttpClient client, final Request request) {
try {
final Response response = client.newCall(request).execute();
final String str = Objects.requireNonNull(response.body()).string();
return new JSONObject(str);
} catch (final IOException e) {
e.printStackTrace();
}
return buildErrorResponse("Unable to execute request");
}
I have no "fields" to create mocks for (my usual MO!), any tips muchappreciated. I can force an error easily enough but to test full flow at least until the POST
You can mock the web application that receives the post and verify that the correct data is send. E.g. you can use http://mock-server.com for this.
Related
I have created a cloud function to print greetings like "Hello David!". my function below:
public void service(HttpRequest request, HttpResponse response)
throws IOException {
String name = request.getFirstQueryParameter("name").orElse("world");
try {
JsonElement requestParsed = gson.fromJson(request.getReader(), JsonElement.class);
JsonObject requestJson = null;
if (requestParsed != null && requestParsed.isJsonObject()) {
requestJson = requestParsed.getAsJsonObject();
}
if (requestJson != null && requestJson.has("name")) {
name = requestJson.get("name").getAsString();
}
} catch (JsonParseException e) {
logger.severe("Error parsing JSON: " + e.getMessage());
}
var writer = new PrintWriter(response.getWriter());
writer.printf("Hello %s!", name);
}
I have written a integration test like below:
#BeforeEach
public void setUp() throws IOException {
String baseDir = System.getProperty("user.dir");
emulatorProcess = new ProcessBuilder()
.command("./../gradlew", "alo")
.directory(new File(baseDir))
.start();
}
#AfterEach
public void tearDown() throws IOException {
InputStream stdoutStream = emulatorProcess.getInputStream();
ByteArrayOutputStream stdoutBytes = new ByteArrayOutputStream();
stdoutBytes.write(stdoutStream.readNBytes(stdoutStream.available()));
System.out.println(stdoutBytes.toString(StandardCharsets.UTF_8));
if (emulatorProcess.isAlive()) {
emulatorProcess.destroy();
}
}
#Test
void helloHttp_shouldRunWithFunctionsFramework() throws Throwable {
String functionUrl = BASE_URL + "/helloHttp";
HttpRequest getRequest = HttpRequest.newBuilder().uri(URI.create(functionUrl)).GET().build();
RetryRegistry registry = RetryRegistry.of(RetryConfig.custom()
.maxAttempts(6)
.intervalFunction(IntervalFunction.ofExponentialBackoff(200, 2))
.retryExceptions(IOException.class)
.retryOnResult(body -> body.toString().length() == 0)
.build());
Retry retry = registry.retry("my");
String body = Retry.decorateCheckedSupplier(retry, () -> client.send(
getRequest,
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)).body()
).apply();
assertThat(body).isEqualTo("Hello world!");
}
So I want to fake a params name in the integration test to pass to my GCP function.
so in my GCP function I can take it like this: name = requestJson.get("name").getAsString();. How do I do it?
I just search it out and the answer is: add post method like this
HttpRequest getRequest = HttpRequest
.newBuilder()
.uri(URI.create(functionUrl))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"David\"}"))
.build();
#Service
public class PokemonManager implements PokemonService {
private HttpResponse<String> getStringHttpResponseByUrl(final String url) {
HttpClient httpClient = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.GET().header("accept", "application/json")
.uri(URI.create(url)).build();
HttpResponse<String> httpResponse = null;
try {
httpResponse = httpClient.send(request, HttpResponse.BodyHandlers.ofString());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
return httpResponse;
}
private <T> T getObjectResponse(T t, String url) {
ObjectMapper objectMapper = new ObjectMapper();
try {
t = objectMapper.readValue(getStringHttpResponseByUrl(url).body(), new TypeReference<>() {
});
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return t;
}
private List<Pokemon> getAllPokemonsAsList() {
final String POSTS_API_URL = "https://pokeapi.co/api/v2/pokemon?limit=10000";
PokeApiResponse pokeApiResponse = new PokeApiResponse();
pokeApiResponse = getObjectResponse(pokeApiResponse, POSTS_API_URL);
System.out.println(pokeApiResponse);
return pokeApiResponse.results;
}
#Override
public List<Pokemon> getAll() {
return getAllPokemonsAsList();
}
I have a code as above. If I do not use generics in the "getObjectResponse" method, the code works fine. However, when I use generics, the type of "t" becomes "LinkedHashMap" instead of "PokeApiResponse", and the code crashes. How can I fix this problem?
Generally you would use it:
objectMapper.readValue("yourJSONHere", PokeApiResponse.class);
If you wanted a Generic T response perhaps this would work
private <T> T getGeneric(Class<T> clazz, String json) throws IOException {
return new ObjectMapper().readValue(json, clazz);
}
Example:
Pokemon charmander = getGeneric(Pokemon.class, "{\n" +
" \"name\": \"charmander\"\n" +
"}");
You are not passing enough information for ObjectMapper to parse the JSON this way. Also there is no need to pass the instance of response, you can use the Class instead. I would also extract json parsing logic to separate method:
public static <T> T jsonToModel(String document, Class<T> type) throws IOException {
return new ObjectMapper().readValue(document, type);
}
private List<Pokemon> getAllPokemonsAsList() {
final String postsApiUrl = "https://pokeapi.co/api/v2/pokemon?limit=10000";
final HttpResponse<String> httpResponse = getStringHttpResponseByUrl(postsApiUrl);
final PokeApiResponse pokeApiResponse = jsonToModel(pokeApiResponse, PokeApiResponse.class);
System.out.println(pokeApiResponse);
return pokeApiResponse.results;
}
I use okhttp to be my httpclient. I think it's a good api but the doc is not so detailed.
how to use it to make a http post request with file uploading?
public Multipart createMultiPart(File file){
Part part = (Part) new Part.Builder().contentType("").body(new File("1.png")).build();
//how to set part name?
Multipart m = new Multipart.Builder().addPart(part).build();
return m;
}
public String postWithFiles(String url,Multipart m) throws IOException{
ByteArrayOutputStream out = new ByteArrayOutputStream();
m.writeBodyTo(out)
;
Request.Body body = Request.Body.create(MediaType.parse("application/x-www-form-urlencoded"),
out.toByteArray());
Request req = new Request.Builder().url(url).post(body).build();
return client.newCall(req).execute().body().string();
}
my question is:
how to set part name? in the form, the file should be named file1.
how to add other fields in the form?
Here is a basic function that uses okhttp to upload a file and some arbitrary field (it literally simulates a regular HTML form submission)
Change the mime type to match your file (here I am assuming .csv) or make it a parameter to the function if you are going to upload different file types
public static Boolean uploadFile(String serverURL, File file) {
try {
RequestBody requestBody = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/csv"), file))
.addFormDataPart("some-field", "some-value")
.build();
Request request = new Request.Builder()
.url(serverURL)
.post(requestBody)
.build();
client.newCall(request).enqueue(new Callback() {
#Override
public void onFailure(final Call call, final IOException e) {
// Handle the error
}
#Override
public void onResponse(final Call call, final Response response) throws IOException {
if (!response.isSuccessful()) {
// Handle the error
}
// Upload successful
}
});
return true;
} catch (Exception ex) {
// Handle the error
}
return false;
}
Note: because it is async call, the boolean return type does not indicate successful upload but only that the request was submitted to okhttp queue.
Here's an answer that works with OkHttp 3.2.0:
public void upload(String url, File file) throws IOException {
OkHttpClient client = new OkHttpClient();
RequestBody formBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", file.getName(),
RequestBody.create(MediaType.parse("text/plain"), file))
.addFormDataPart("other_field", "other_field_value")
.build();
Request request = new Request.Builder().url(url).post(formBody).build();
Response response = client.newCall(request).execute();
}
Note: this answer is for okhttp 1.x/2.x. For 3.x, see this other answer.
The class Multipart from mimecraft encapsulates the whole HTTP body and can handle regular fields like so:
Multipart m = new Multipart.Builder()
.type(Multipart.Type.FORM)
.addPart(new Part.Builder()
.body("value")
.contentDisposition("form-data; name=\"non_file_field\"")
.build())
.addPart(new Part.Builder()
.contentType("text/csv")
.body(aFile)
.contentDisposition("form-data; name=\"file_field\"; filename=\"file1\"")
.build())
.build();
Take a look at examples of multipart/form-data encoding to get a sense of how you need to construct the parts.
Once you have a Multipart object, all that's left to do is specify the right Content-Type header and pass on the body bytes to the request.
Since you seem to be working with the v2.0 of the OkHttp API, which I don't have experience with, this is just guess code:
// You'll probably need to change the MediaType to use the Content-Type
// from the multipart object
Request.Body body = Request.Body.create(
MediaType.parse(m.getHeaders().get("Content-Type")),
out.toByteArray());
For OkHttp 1.5.4, here is a stripped down code I'm using which is adapted from a sample snippet:
OkHttpClient client = new OkHttpClient();
OutputStream out = null;
try {
URL url = new URL("http://www.example.com");
HttpURLConnection connection = client.open(url);
for (Map.Entry<String, String> entry : multipart.getHeaders().entrySet()) {
connection.addRequestProperty(entry.getKey(), entry.getValue());
}
connection.setRequestMethod("POST");
// Write the request.
out = connection.getOutputStream();
multipart.writeBodyTo(out);
out.close();
// Read the response.
if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
throw new IOException("Unexpected HTTP response: "
+ connection.getResponseCode() + " " + connection.getResponseMessage());
}
} finally {
// Clean up.
try {
if (out != null) out.close();
} catch (Exception e) {
}
}
I've created cool helper class for OkHttp3. it here
public class OkHttp3Helper {
public static final String TAG;
private static final okhttp3.OkHttpClient client;
static {
TAG = OkHttp3Helper.class.getSimpleName();
client = new okhttp3.OkHttpClient.Builder()
.readTimeout(7, TimeUnit.MINUTES)
.writeTimeout(7, TimeUnit.MINUTES)
.build();
}
private Context context;
public OkHttp3Helper(Context context) {
this.context = context;
}
/**
* <strong>Uses:</strong><br/>
* <p>
* {#code
* ArrayMap<String, String> formField = new ArrayMap<>();}
* <br/>
* {#code formField.put("key1", "value1");}<br/>
* {#code formField.put("key2", "value2");}<br/>
* {#code formField.put("key3", "value3");}<br/>
* <br/>
* {#code String response = helper.postToServer("http://www.example.com/", formField);}<br/>
* </p>
*
* #param url String
* #param formField android.support.v4.util.ArrayMap
* #return response from server in String format
* #throws Exception
*/
#NonNull
public String postToServer(#NonNull String url, #Nullable ArrayMap<String, String> formField)
throws Exception {
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);
if (formField != null) {
okhttp3.FormBody.Builder formBodyBuilder = new okhttp3.FormBody.Builder();
for (Map.Entry<String, String> entry : formField.entrySet()) {
formBodyBuilder.add(entry.getKey(), entry.getValue());
}
requestBuilder.post(formBodyBuilder.build());
}
okhttp3.Request request = requestBuilder.build();
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException(response.message());
}
return response.body().string();
}
/**
* <strong>Uses:</strong><br/>
* <p>
* {#code
* ArrayMap<String, String> formField = new ArrayMap<>();}
* <br/>
* {#code formField.put("key1", "value1");}<br/>
* {#code formField.put("key2", "value2");}<br/>
* {#code formField.put("key3", "value3");}<br/>
* <br/>
* {#code
* ArrayMap<String, File> filePart = new ArrayMap<>();}
* <br/>
* {#code filePart.put("key1", new File("pathname"));}<br/>
* {#code filePart.put("key2", new File("pathname"));}<br/>
* {#code filePart.put("key3", new File("pathname"));}<br/>
* <br/>
* {#code String response = helper.postToServer("http://www.example.com/", formField, filePart);}<br/>
* </p>
*
* #param url String
* #param formField android.support.v4.util.ArrayMap
* #param filePart android.support.v4.util.ArrayMap
* #return response from server in String format
* #throws Exception
*/
#NonNull
public String postMultiPartToServer(#NonNull String url,
#Nullable ArrayMap<String, String> formField,
#Nullable ArrayMap<String, File> filePart)
throws Exception {
okhttp3.Request.Builder requestBuilder = new okhttp3.Request.Builder().url(url);
if (formField != null || filePart != null) {
okhttp3.MultipartBody.Builder multipartBodyBuilder = new okhttp3.MultipartBody.Builder();
multipartBodyBuilder.setType(okhttp3.MultipartBody.FORM);
if (formField != null) {
for (Map.Entry<String, String> entry : formField.entrySet()) {
multipartBodyBuilder.addFormDataPart(entry.getKey(), entry.getValue());
}
}
if (filePart != null) {
for (Map.Entry<String, File> entry : filePart.entrySet()) {
File file = entry.getValue();
multipartBodyBuilder.addFormDataPart(
entry.getKey(),
file.getName(),
okhttp3.RequestBody.create(getMediaType(file.toURI()), file)
);
}
}
requestBuilder.post(multipartBodyBuilder.build());
}
okhttp3.Request request = requestBuilder.build();
okhttp3.Response response = client.newCall(request).execute();
if (!response.isSuccessful()) {
throw new IOException(response.message());
}
return response.body().string();
}
private okhttp3.MediaType getMediaType(URI uri1) {
Uri uri = Uri.parse(uri1.toString());
String mimeType;
if (uri.getScheme().equals(ContentResolver.SCHEME_CONTENT)) {
ContentResolver cr = context.getContentResolver();
mimeType = cr.getType(uri);
} else {
String fileExtension = MimeTypeMap.getFileExtensionFromUrl(uri
.toString());
mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
fileExtension.toLowerCase());
}
return okhttp3.MediaType.parse(mimeType);
}
}
OkHttpClient client = new OkHttpClient.Builder().connectTimeout(10, TimeUnit.SECONDS).writeTimeout(180, TimeUnit.SECONDS).readTimeout(180, TimeUnit.SECONDS).build();
RequestBody body = new MultipartBody.Builder().setType(MultipartBody.FORM)
.addFormDataPart("File", path.getName(),RequestBody.create(MediaType.parse("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"),path))
.addFormDataPart("username", username)
.addFormDataPart("password", password)
.build();
Request request = new Request.Builder().url(url).post(body).build();
Response response = client.newCall(request).execute();
result = response.body().string();
Above code will send the username, password as the post parameter and the file will be uploaded in the name of "File".
PHP Server will receive the files
if (isset($_FILES["File"]) &&
isset($_POST['username']) &&
isset($_POST['password'])) {
//All Values found
}else{
echo 'please send the required data';
}
Perfect code for uploading any files to google drive along with metadata of files easily.
String url = String.format("https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart");
//String url = String.format("https://www.googleapis.com/upload/drive/v2/files?uploadType=resumable");
boolean status;
String metaDataFile = "{\"title\":\"" + step.getFile_name() + "\"," +
"\"description\":\"" + step.getDescription() + "\"," +
"\"parents\":[{\"id\":\"" + step.getFolderId() + "\"}]," +
"\"capabilities\":{\"canEdit\":\"" + false + "\", \"canDownload\":\" "+ false +" \" }, " +
"\"type\":\"" + step.getFile_access() + "\"" +
"}";
//get the encoded byte data for decode
byte[] file = Base64.decodeBase64(step.getFile_data());
//attaching metadata to our request object
RequestBody requestBodyMetaData = RequestBody.create(MediaType.parse("application/json"), metaDataFile);
//passing both meta data and file content for uploading
RequestBody requestBodyMultipart = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("metadata", null, requestBodyMetaData)
.addFormDataPart("file", null, RequestBody.create(MediaType.parse("application/octet-stream"), file))
.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", String.format("Bearer %s", step.getAccess_token()))
.post(requestBodyMultipart)
.build();
OkHttpClient okHttpClient = new OkHttpClient();
try {
// Get response after rest call.
Response response = okHttpClient.newCall(request).execute();
status = response.code() == 200 ? true : false;
map.put(step.getOutput_variable(), response.code());
Asynchronously ...
public void UploadFileFromOkhttp(String filePath, String jwtToken){
String url = "https://api.baserow.io/api/user-files/upload-file/";
MultipartBody.Builder builder = new MultipartBody.Builder();
builder.setType(MultipartBody.FORM);
File file = new File(filePath);
builder.addFormDataPart("file" , file.getName() , RequestBody.create(MediaType.parse("image/*"), file));
RequestBody requestBody = builder.build();
Request request = new Request.Builder()
.url(url)
.addHeader("Authorization", "JWT "+ jwtToken)
.post(requestBody)
.build();
okHttpClient.newCall(request).enqueue(new okhttp3.Callback() {
#Override
public void onFailure(#NotNull Call call, #NotNull IOException e) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
OnError(e.getMessage());
}
});
}
#Override
public void onResponse(#NotNull Call call, #NotNull Response response) throws IOException {
final String responseData = response.body().string();
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
OnSuccess(responseData);
}
});
}
});
}
I wrote a Web API using Apache CXF. When I use HttpServletRequest.getParamter() in a post method, it return null.Here is the code:
#Path("/")
public class TokenService extends DigiwinBaseService {
private static void printRequest(HttpServletRequest httpRequest) {
System.out.println("\n\n Headers");
Enumeration headerNames = httpRequest.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
}
System.out.println("\n\n Parameters");
Enumeration params = httpRequest.getParameterNames();
while (params.hasMoreElements()) {
String paramName = (String) params.nextElement();
System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
}
System.out.println("\n\n Row data");
System.out.println(extractPostRequestBody(httpRequest));
}
private static String extractPostRequestBody(HttpServletRequest request) {
if ("POST".equalsIgnoreCase(request.getMethod())) {
Scanner s = null;
try {
s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
} catch (IOException e) {
e.printStackTrace();
}
return s.hasNext() ? s.next() : "null";
}
return "null";
}
#POST
#Consumes("application/x-www-form-urlencoded")
public Response Authorize(#FormParam("param") String param,
#FormParam("param2") String param2,#Context HttpServletRequest httpRequest) throws OAuthSystemException {
printRequest(httpRequest);
System.out.println("param:"+param);
System.out.println("param2:"+param2);
return Response.status(HttpServletResponse.SC_OK).entity("OK").build();
}
}
Here is the test code
public class HttpClientTest {
public static void main(String[] args) throws Exception{
String url4 = "/api/services/Test";
String host = "127.0.0.1";
HttpClient httpClient = new HttpClient();
httpClient.getHostConfiguration().setHost(host, 8080, "http");
HttpMethod method = postMethod(url4);
httpClient.executeMethod(method);
String response = method.getResponseBodyAsString();
System.out.println(response);
}
private static HttpMethod postMethod(String url) throws IOException{
PostMethod post = new PostMethod(url);
post.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=gbk");
NameValuePair[] param = {
new NameValuePair("param","param1"),
new NameValuePair("param2","param2"),} ;
post.setRequestBody(param);
post.releaseConnection();
return post;
}
}
Here is the print out :
Headers
content-type = application/x-www-form-urlencoded;charset=gbk
user-agent = Jakarta Commons-HttpClient/3.1
host = 127.0.0.1:8080
content-length = 26
Parameters
Row data
null
param:param1
param2:param2
Why the Parameters is null? How can i get post params using HttpServletRequest.getParamter()
CXF is consuming the POST data to fill the FormParams.
https://issues.apache.org/jira/browse/CXF-2993
The resolution is "won't fix". In the issue, they suggest to use a MultivaluedMap to recover all params, or use only the HttpServletRequest
Option 1
#POST
#Consumes("application/x-www-form-urlencoded")
public Response Authorize( MultivaluedMap<String, String> parameterMap, #Context HttpServletRequest httpRequest) throws OAuthSystemException {
//parameterMap has your POST parameters
Option 2
#POST
#Consumes("application/x-www-form-urlencoded")
public Response Authorize( #Context HttpServletRequest httpRequest) throws OAuthSystemException {
//httpRequest.getParameterMap() has your POST parameters
I am using commons HttpClient to make an http call to a Spring servlet. I need to add a few parameters in the query string. So I do the following:
HttpRequestBase request = new HttpGet(url);
HttpParams params = new BasicHttpParams();
params.setParameter("key1", "value1");
params.setParameter("key2", "value2");
params.setParameter("key3", "value3");
request.setParams(params);
HttpClient httpClient = new DefaultHttpClient();
httpClient.execute(request);
However when i try to read the parameter in the servlet using
((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest().getParameter("key");
it returns null. In fact the parameterMap is completely empty. When I manually append the parameters to the url before creating the HttpGet request, the parameters are available in the servlet. Same when I hit the servlet from the browser using the URL with queryString appended.
What's the error here? In httpclient 3.x, GetMethod had a setQueryString() method to append the querystring. What's the equivalent in 4.x?
Here is how you would add query string parameters using HttpClient 4.2 and later:
URIBuilder builder = new URIBuilder("http://example.com/");
builder.setParameter("parts", "all").setParameter("action", "finish");
HttpPost post = new HttpPost(builder.build());
The resulting URI would look like:
http://example.com/?parts=all&action=finish
If you want to add a query parameter after you have created the request, try casting the HttpRequest to a HttpBaseRequest. Then you can change the URI of the casted request:
HttpGet someHttpGet = new HttpGet("http://google.de");
URI uri = new URIBuilder(someHttpGet.getURI()).addParameter("q",
"That was easy!").build();
((HttpRequestBase) someHttpGet).setURI(uri);
The HttpParams interface isn't there for specifying query string parameters, it's for specifying runtime behaviour of the HttpClient object.
If you want to pass query string parameters, you need to assemble them on the URL yourself, e.g.
new HttpGet(url + "key1=" + value1 + ...);
Remember to encode the values first (using URLEncoder).
I am using httpclient 4.4.
For solr query I used the following way and it worked.
NameValuePair nv2 = new BasicNameValuePair("fq","(active:true) AND (category:Fruit OR category1:Vegetable)");
nvPairList.add(nv2);
NameValuePair nv3 = new BasicNameValuePair("wt","json");
nvPairList.add(nv3);
NameValuePair nv4 = new BasicNameValuePair("start","0");
nvPairList.add(nv4);
NameValuePair nv5 = new BasicNameValuePair("rows","10");
nvPairList.add(nv5);
HttpClient client = HttpClientBuilder.create().build();
HttpGet request = new HttpGet(url);
URI uri = new URIBuilder(request.getURI()).addParameters(nvPairList).build();
request.setURI(uri);
HttpResponse response = client.execute(request);
if (response.getStatusLine().getStatusCode() != 200) {
}
BufferedReader br = new BufferedReader(
new InputStreamReader((response.getEntity().getContent())));
String output;
System.out.println("Output .... ");
String respStr = "";
while ((output = br.readLine()) != null) {
respStr = respStr + output;
System.out.println(output);
}
This approach is ok but will not work for when you get params dynamically , sometimes 1, 2, 3 or more, just like a SOLR search query (for example)
Here is a more flexible solution. Crude but can be refined.
public static void main(String[] args) {
String host = "localhost";
String port = "9093";
String param = "/10-2014.01?description=cars&verbose=true&hl=true&hl.simple.pre=<b>&hl.simple.post=</b>";
String[] wholeString = param.split("\\?");
String theQueryString = wholeString.length > 1 ? wholeString[1] : "";
String SolrUrl = "http://" + host + ":" + port + "/mypublish-services/carclassifications/" + "loc";
GetMethod method = new GetMethod(SolrUrl );
if (theQueryString.equalsIgnoreCase("")) {
method.setQueryString(new NameValuePair[]{
});
} else {
String[] paramKeyValuesArray = theQueryString.split("&");
List<String> list = Arrays.asList(paramKeyValuesArray);
List<NameValuePair> nvPairList = new ArrayList<NameValuePair>();
for (String s : list) {
String[] nvPair = s.split("=");
String theKey = nvPair[0];
String theValue = nvPair[1];
NameValuePair nameValuePair = new NameValuePair(theKey, theValue);
nvPairList.add(nameValuePair);
}
NameValuePair[] nvPairArray = new NameValuePair[nvPairList.size()];
nvPairList.toArray(nvPairArray);
method.setQueryString(nvPairArray); // Encoding is taken care of here by setQueryString
}
}
This is how I implemented my URL builder.
I have created one Service class to provide the params for the URL
public interface ParamsProvider {
String queryProvider(List<BasicNameValuePair> params);
String bodyProvider(List<BasicNameValuePair> params);
}
The Implementation of methods are below
#Component
public class ParamsProviderImp implements ParamsProvider {
#Override
public String queryProvider(List<BasicNameValuePair> params) {
StringBuilder query = new StringBuilder();
AtomicBoolean first = new AtomicBoolean(true);
params.forEach(basicNameValuePair -> {
if (first.get()) {
query.append("?");
query.append(basicNameValuePair.toString());
first.set(false);
} else {
query.append("&");
query.append(basicNameValuePair.toString());
}
});
return query.toString();
}
#Override
public String bodyProvider(List<BasicNameValuePair> params) {
StringBuilder body = new StringBuilder();
AtomicBoolean first = new AtomicBoolean(true);
params.forEach(basicNameValuePair -> {
if (first.get()) {
body.append(basicNameValuePair.toString());
first.set(false);
} else {
body.append("&");
body.append(basicNameValuePair.toString());
}
});
return body.toString();
}
}
When we need the query params for our URL, I simply call the service and build it.
Example for that is below.
Class Mock{
#Autowired
ParamsProvider paramsProvider;
String url ="http://www.google.lk";
// For the query params price,type
List<BasicNameValuePair> queryParameters = new ArrayList<>();
queryParameters.add(new BasicNameValuePair("price", 100));
queryParameters.add(new BasicNameValuePair("type", "L"));
url = url+paramsProvider.queryProvider(queryParameters);
// You can use it in similar way to send the body params using the bodyProvider
}
Im using Java 8 and apache httpclient 4.5.13
HashMap<String, String> customParams = new HashMap<>();
customParams.put("param1", "ABC");
customParams.put("param2", "123");
URIBuilder uriBuilder = new URIBuilder(baseURL);
for (String paramKey : customParams.keySet()) {
uriBuilder.addParameter(paramKey, customParams.get(paramKey));
}
System.out.println(uriBuilder.build().toASCIIString()); // ENCODED URL
System.out.println(uriBuilder.build().toString); // NORMAL URL
Full example with DTO
public class HttpResponseDTO {
private Integer statusCode;
private String body;
private String errorMessage;
public Integer getStatusCode() {
return statusCode;
}
public void setStatusCode(Integer statusCode) {
this.statusCode = statusCode;
}
public String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getErrorMessage() {
return errorMessage;
}
public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}
/**
*
* #param destinationURL
* #param params
* #param headers
* #return HttpResponseDTO
*/
public static HttpResponseDTO get(String baseURL, Boolean encodeURL, HashMap<String, String> params, HashMap<String, String> headers) {
final HttpResponseDTO httpResponseDTO = new HttpResponseDTO();
// ADD PARAMS IF
if (params != null && Boolean.FALSE.equals(params.isEmpty())) {
URIBuilder uriBuilder;
try {
uriBuilder = new URIBuilder(baseURL);
for (String paramKey : params.keySet()) {
uriBuilder.addParameter(paramKey, params.get(paramKey));
}
// CODIFICAR URL ?
if (Boolean.TRUE.equals(encodeURL)) {
baseURL = uriBuilder.build().toASCIIString();
} else {
baseURL = uriBuilder.build().toString();
}
} catch (URISyntaxException e) {
httpResponseDTO.setStatusCode(500);
httpResponseDTO.setErrorMessage("ERROR AL CODIFICAR URL: " + e.getMessage());
return httpResponseDTO;
}
}
// HACER PETICION HTTP
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
final HttpGet get = new HttpGet(baseURL);
// ADD HEADERS
if (headers != null && Boolean.FALSE.equals(headers.isEmpty())) {
for (String headerKey : headers.keySet()) {
get.setHeader(headerKey, headers.get(headerKey));
}
}
try (CloseableHttpResponse response = httpClient.execute(get);) {
HttpEntity httpEntity = response.getEntity();
if (httpEntity != null) {
httpResponseDTO.setBody(EntityUtils.toString(httpEntity));
httpResponseDTO.setStatusCode(response.getStatusLine().getStatusCode());
}
} catch(Exception e) {
httpResponseDTO.setStatusCode(500);
httpResponseDTO.setErrorMessage(e.getMessage());
return httpResponseDTO;
}
} catch(Exception e) {
httpResponseDTO.setStatusCode(500);
httpResponseDTO.setErrorMessage(e.getMessage());
return httpResponseDTO;
}
return httpResponseDTO;
}