I'm trying to send aמ HTTP POST request in order to send contacts information to a Mail Exchange Server, using their API (creating a new "subscriber"). I'm using Java and java.util.HttpURLConnection.
When I try signing the connection, I'm getting a null reference exception. If I try signing the connection prior to adding the setRequestProperty headers, I'm getting an Invalid Signature response from the server.
Using a GET request with the same general procedure works - which means, as far as I understand, that my signing method (and key values etc.) is OK.
The service I'm trying to use has some kind of a "SDK" available, written in .NET. I didn't try to use it but I do believe it to work (they declare so).
I tried to replicate their procedure. Below you can find my code, follow by theirs:
private static HttpURLConnection createAndSendOAuthPostRequestWithParams () throws MalformedURLException, IOException, Exception {
String url = "http://apisdomain/v1.0/lists/354467/subscribers";
// Here I set up the values given by the provider (API's admin) which I removed from the example
String clientKey = "";
String clientSecret = "";
String userKey = "";
String userSecret = "";
String postData = "NAME=TestSubscriber&EMAIL=test#gmail.com
byte[] postBody = postData.getBytes("UTF-8");
URL apiUrl = new URL(url);
HttpURLConnection connection = (HttpURLConnection) apiUrl.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("content-length", String.valueOf(postBody.length));
connection.setRequestProperty("content-type", "application/x-www-form-urlencoded; charset=UTF-8");
//OAuth
OAuthConsumer consumer = new DefaultOAuthConsumer (clientKey, clientSecret);
//consumer.setAdditionalParameters(parameters);
consumer.setTokenWithSecret(userKey, userSecret);
HttpRequest httpReq = consumer.sign(connection); //Where the exception occurs
if (!postBody.toString().isEmpty()) {
connection.setDoOutput(true);
try (DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream())) {
outputStream.write(postBody);
outputStream.flush();
}
}
return connection;
}
From thier SDK:
using System.Text;
namespace ResponderSDK
{
using OAuth;
using System;
using System.Collections.Generic;
using System.Net;
using System.IO;
class ResponderOAuth
{
/* Contains the last HTTP status code returned. */
public HttpStatusCode http_code;
/* Contains the last API call. */
public string url;
/* Set up the API root URL. */
public string host = "http://api.responder.co.il/v1.0/";
/* Set timeout default. */
public int timeout = 3000;
/* Set connect timeout. */
public int connect_timeout = 30;
/* Verify SSL Cert. */
public bool ssl_verifypeer = false;
/* Response format. */
public string format = "json";
/* Contains the last HTTP headers returned. */
public string http_info;
/* Set the useragent. */
public string useragent = "ResponderOAuth v0.1-beta";
/*debug info*/
public string headers_string;
public string base_string;
public string post_string;
/* Signature */
private OAuthSignatureMethod_HMAC_SHA1 signature;
/* OAuthConsumer */
private OAuthConsumer consumer;
/* Token */
private OAuthToken token;
public ResponderOAuth(string consumer_key, string consumer_secret, string oauth_token = null, string oauth_token_secret = null)
{
this.signature = new OAuthSignatureMethod_HMAC_SHA1();
this.consumer = new OAuthConsumer(consumer_key, consumer_secret);
if (!String.IsNullOrEmpty(oauth_token) && !String.IsNullOrEmpty(oauth_token_secret))
{
this.token = new OAuthToken(oauth_token, oauth_token_secret);
}
else
{
this.token = null;
}
}
public string http_request(string url, string method = "GET", ParametersArray parameters = null)
{
method = method.ToUpper();
if (url.LastIndexOf("https://") != 0 && url.LastIndexOf("http://") != 0)
{
url = String.Format("{0}{1}", this.host, url);
}
if (method.Equals("GET"))
parameters = null;
OAuthRequest request = OAuthRequest.from_consumer_and_token(this.consumer, this.token, method, url, parameters);
request.sign_request(this.signature, this.consumer, this.token);
this.base_string = request.base_string;
if (method.Equals("GET"))
return this.http(request.to_url(), "GET", request.to_header(), null);
else
return this.http(request.get_normalized_http_url(), method, request.to_header(), request.to_postdata());
}
private string http(string url, string method, WebHeaderCollection headers, string data = null)
{
List<string> new_http_info = new List<string>();
ServicePointManager.ServerCertificateValidationCallback = new System.Net.Security.RemoteCertificateValidationCallback(AcceptAllCertifications);
HttpWebRequest request = null;
if (!method.Equals("DELETE"))
request = (HttpWebRequest)WebRequest.Create(url);
else
{
if (!String.IsNullOrEmpty(data))
{
url = String.Format("{0}?{1}", url, data);
}
request = (HttpWebRequest)WebRequest.Create(url);
}
/* WebRequest settings */
((HttpWebRequest)request).ProtocolVersion = System.Net.HttpVersion.Version10;
((HttpWebRequest)request).UserAgent = this.useragent;
((HttpWebRequest)request).ContinueTimeout = this.connect_timeout;
((HttpWebRequest)request).Timeout = this.timeout;
((HttpWebRequest)request).Headers = headers;
((HttpWebRequest)request).UseDefaultCredentials = true;
((HttpWebRequest)request).PreAuthenticate = true;
((HttpWebRequest)request).Credentials = CredentialCache.DefaultCredentials;
this.headers_string = headers.ToString();
this.post_string = data;
byte[] dataByteArray = null;
if ((!String.IsNullOrEmpty(data) && method.Equals("POST")) || method.Equals("PUT"))
{
((HttpWebRequest)request).ContentType = "application/x-www-form-urlencoded";
System.Text.Encoding encoding = System.Text.Encoding.UTF8;
dataByteArray = encoding.GetBytes(data);
((HttpWebRequest)request).ContentLength = dataByteArray.Length;
((HttpWebRequest)request).Expect = "";
}
switch (method)
{
case "POST":
((HttpWebRequest)request).Method = "POST";
if (!String.IsNullOrEmpty(data))
{
Stream dataPost = request.GetRequestStream();
dataPost.Write(dataByteArray, 0, dataByteArray.Length);
dataPost.Close();
}
break;
case "PUT":
((HttpWebRequest)request).Method = "PUT";
if (!String.IsNullOrEmpty(data))
{
Stream dataPost = request.GetRequestStream();
dataPost.Write(dataByteArray, 0, dataByteArray.Length);
dataPost.Close();
}
break;
case "DELETE":
((HttpWebRequest)request).Method = "DELETE";
break;
}
WebResponse response = request.GetResponse();
this.http_code = ((HttpWebResponse)response).StatusCode;
// Get the stream containing content returned by the server.
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
return reader.ReadToEnd();
}
}
}
If your input String format is json, you can change content-type to "application/json" and try signing in after adding the setRequestProperty headers.
Related
I have tried to fetch data from an API which has a key. But in the output it says "app key not found".
I have tested it on Postman and it works properly.
Here is my code:
public class fetchData extends AsyncTask<Void,Void,Void> {
String data="";
#Override
protected Void doInBackground(Void... voids) {
try {
URL url=new URL("https://app.inyek.com/app_api/api_extra/all_order.php?");
HttpURLConnection con=(HttpURLConnection) url.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded/json;charset=UTF-8");
con.setRequestProperty("app_key","whatever");
con.setDoOutput(true);
}
I strongly suggest you make an Abstract HttpRequestTask which extends AsyncTask. In this abstract ancestor you can make some helper methods for reading your input, something like so:
/**
* HttpRequestTask is an abstract extension of an AsyncTask for HTTP Requests.
*
* #param <P>
* Type for parameter(s) to doInBackground (can be Void if none provided)
* #param <R>
* Type for result of request (can be Void if ignored, or using listeners.)
*/
public abstract class HttpRequestTask<P, R> extends AsyncTask<P, Integer, R>
{
private static final String TAG = "HttpRequestTask";
// Post form encoded requests, get back JSON response
private static final RequestMethod DEFAULT_REQUEST_METHOD = RequestMethod.POST;
private static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded;charset=UTF-8;";
private static final String DEFAULT_ACCEPT = "application/json;";
private static final int DEFAULT_TIMEOUT = 8000; // 8 seconds
private static final String CHARSET = "UTF-8";
protected static final String NULL_CONTEXT = "Context is null.";
protected static final String INVALID_RESPONSE = "The server did not send back a valid response.";
// Request methods supported by back-end
protected enum RequestMethod
{
GET("GET"),
POST("POST");
private final String method;
RequestMethod(String method)
{
this.method = method;
}
#Override
public String toString()
{
return this.method;
}
}
/**
* ALWAYS use application context here to prevent memory leaks.
*
*/
protected HttpRequestTask(#NonNull final Context context)
{
this.context = context;
}
protected void verifyConnection() throws IOException
{
if (!SystemUtil.isInternetAvailable(context))
{
throw new IOException("Internet is unavailable.");
}
}
/**
* Creates and opens a URLConnection for the url parameter, as well as setting request options.
*
* #param url
* to connect to.
*
* #return opened HTTPURLConnection for POSTing data to ctservices.
*/
protected HttpURLConnection getURLConnection(URL url) throws IOException
{
return this.getURLConnection(url, DEFAULT_REQUEST_METHOD, DEFAULT_CONTENT_TYPE,
DEFAULT_ACCEPT, DEFAULT_TIMEOUT);
}
/**
* Creates and opens a URLConnection for the url parameter, as well as setting request options.
*
* #param url
* to connect to.
*
* #return opened HTTPURLConnection
*/
protected HttpURLConnection getURLConnection(#NonNull final URL url,
#NonNull final RequestMethod requestMethod,
#NonNull final String contentType,
#Nullable final String accept, final int timeout)
throws IOException
{
verifyConnection();
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod(requestMethod.toString());
urlConnection.setRequestProperty("Content-Type", contentType);
if (accept != null && !accept.isEmpty())
{
urlConnection.setRequestProperty("Accept", accept);
}
urlConnection.setReadTimeout(timeout);
urlConnection.setConnectTimeout(timeout);
urlConnection.setUseCaches(false);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
return urlConnection;
}
/**
* Creates and opens a URLConnection for the url parameter, but does not set any request options.
*
* #param url
* to connect to.
*
* #return opened HTTPURLConnection without parameters set.
*/
protected HttpURLConnection getBasicURLConnection(URL url) throws IOException
{
if (!SystemUtil.isInternetAvailable(applicationContext.get()))
{
throw new IOException("Internet is unavailable.");
}
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
return urlConnection;
}
/**
* Write a JSONObject of request parameters to the output stream as form-encoded data.
*
* #param urlConnection
* opened urlConnection with output enabled (done by getURLConnection).
* #param params
* to write to request.
*
* #throws IOException
* problem writing to output stream
*/
protected void writeParams(HttpURLConnection urlConnection, JSONObject params) throws IOException
{
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter outWriter = new BufferedWriter(new OutputStreamWriter(outputStream,
StandardCharsets.UTF_8));
String urlParams = this.encodeJSONObject(params);
outWriter.write(urlParams);
outWriter.flush();
outWriter.close();
outputStream.close();
}
/**
* Reads the response of a URLConnection from the input stream and puts it in a string.
*
* #param urlConnection
* opened urlConnection with input enabled (done by getURLConnection).
*
* #return response string
*
* #throws IOException
* problem reading input stream
*/
protected String readResponse(HttpURLConnection urlConnection) throws IOException
{
InputStream inputStream = null;
try
{
/* If we failed to connect will throw a SocketResponseTimeoutException,
* which is an IOException. */
int responseCode = urlConnection.getResponseCode();
if (HttpURLConnection.HTTP_OK != responseCode)
{
throw new IOException("Bad response code - " + responseCode);
}
inputStream = urlConnection.getInputStream();
final String response = parseInputStream(inputStream);
urlConnection.disconnect();
return response;
}
finally
{
if (inputStream != null)
{
try
{
inputStream.close();
}
catch (Exception e) {}
}
}
}
protected Context getContext()
{
return this.context;
}
protected String getString(final int resId)
{
return getContext().getString(resId);
}
/**
* Encodes a JSONObject as a form-data URL string.
*
* #param jo
* to encode
*
* #return encoded URL string
*/
private String encodeJSONObject(JSONObject jo)
{
StringBuilder sb = new StringBuilder();
boolean first = true;
Iterator<String> itr = jo.keys();
String key;
Object val;
try
{
while (itr.hasNext())
{
key = itr.next();
val = jo.get(key);
if (first)
{
first = false;
}
else
{
sb.append('&');
}
sb.append(URLEncoder.encode(key, CHARSET));
sb.append('=');
sb.append(URLEncoder.encode(val.toString(), CHARSET));
}
}
catch (JSONException | UnsupportedEncodingException e) {}
return sb.toString();
}
private String parseInputStream(InputStream is) throws IOException
{
BufferedReader br = null;
try
{
br = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = br.readLine()) != null)
{
sb.append(line);
}
return sb.toString();
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (Exception e) {}
}
}
}
/**
* Merges any properties of b into a that don't already have a key match in a.
*
* #param a
* merging to
* #param b
* merging from
*
* #return a with any unique values from b
*/
protected JSONObject mergeJSONObjects(JSONObject a, JSONObject b)
{
if (b == null)
{
return a;
}
if (a == null)
{
return b;
}
try
{
Iterator<String> bItr = b.keys();
String key;
while (bItr.hasNext())
{
key = bItr.next();
if (!a.has(key))
{
a.put(key, b.get(key));
}
}
return a;
}
catch (Exception ex)
{
Log.e(TAG, ex.getClass().getSimpleName() + " in mergeJSONObjects: " + ex.getMessage() +
'\n' + Log.getStackTraceString(ex));
return a;
}
}
}
Then you can extend your HttpRequestTask to easily make network requests:
public class ExampleNetworkTask extends HttpRequestTask<Void, Void>
{
private static final String TAG = "ExampleNetworkTask";
private final SimpleListener successListener;
private final StringListener errorListener;
private final String servicesUrl;
public static void start(#NonNull final Context context,
#Nullable final SimpleListener successListener,
#Nullable final StringListener errorListener)
throws IllegalArgumentException
{
if (context == null)
{
throw new IllegalArgumentException(NULL_CONTEXT);
}
new ExampleNetworkTask(context, successListener, errorListener).execute();
}
private ExampleNetworkTask(#NonNull final Context context,
#Nullable final SimpleListener successListener,
#Nullable final StringListener errorListener)
{
super(context);
this.servicesUrl = SystemUtil.getServiceUrl(getContext(), R.string.example_service);
this.successListener = successListener;
this.errorListener = errorListener;
}
#Override
protected Void doInBackground(Void... voids)
{
try
{
final HttpURLConnection urlConnection = super.getURLConnection(new URL(servicesUrl));
final JSONObject params = new JSONObject();
// Add params
params.put("app_key", appKey);
params.put("order_number", orderNumber);
// ...
// Send request, read parse response
super.writeParams(urlConnection, params);
final String response = super.readResponse(urlConnection);
final JSONObject responseObj = new JSONObject(response);
// Handle response
}
catch (Exception ex)
{
final String msg = ex.getLocalizedMessage();
Log.e(TAG, ex.getClass().getSimpleName() + ": " + msg + '\n' +
Log.getStackTraceString(ex));
// Handle network exceptions and other exceptions here.
}
return null;
}
}
In PostMan, how did you specify the app key? was it through an HTTP header?
(Sorry, I would have added a comment, but I do not have enough reputation)
Or was it specified as a GET parameter?
In the latter case, try something like:
URL url=new URL("https://app.inyek.com/app_api/api_extra/all_order.php?app_key=YOUR_KEY");
Welcome to Stack Exchange! Firstly I'd suggest you don't put your API Key within questions and/or images, as they might be sensitive and can be abused by malicious users. Feel free to edit your question and remove them.
To answer your query, I think you need to write the contents to the http request body in a json format. This can be done as per the guide on the following webpage:
https://www.baeldung.com/httpurlconnection-post
In summary, you need to create an output stream and write the contents to it directly.
Thank you guys! finally i got the answer using OkHttpClient. here is the code:
OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/x-www-form-urlencoded");
RequestBody body = RequestBody.create(mediaType, "app_key=whatever");
Request request = new Request.Builder()
.url("https://app.inyek.com/app_api/api_extra/all_order.php")
.post(body)
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("key", "whatever")
.addHeader("cache-control", "no-cache")
.addHeader("Postman-Token", "whatever")
.build();
Response response = client.newCall(request).execute();
This question already has answers here:
Java - sending HTTP parameters via POST method easily
(18 answers)
Closed 5 years ago.
i need to post data to particular url
in which in content i need to post html in content array and in meta headers in json format.
URL oracle = new URL("");
try (BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()))) {
String inputLine1;
while ((inputLine1 = in.readLine()) != null) {
System.out.println(inputLine1);
com.eclipsesource.json.JsonObject object = Json.parse(inputLine1).asObject();
com.eclipsesource.json.JsonArray items = Json.parse(inputLine1).asObject().get("data").asArray();
for (JsonValue item : items) {
//System.out.println(item.toString());
String name = item.asObject().getString("id", "Unknown Item");
System.out.println(name);
String quantity = item.asObject().getString("url", "id");
// JSONArray jsonArray2 = new JSONArray(quantity);
System.out.println(quantity);
/* Platform.runLater(() ->{
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(HV1.class.getName()).log(Level.SEVERE, null, ex);
}*/
Img.load(quantity);
URL url;
InputStream is = null;
BufferedReader br;
String line;
url = new URL(quantity);
is = url.openStream(); // throws an IOException
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
System.out.println(line);
byte[] postData= line.getBytes( StandardCharsets.UTF_8 );
wb2.load(line);
String originalUrl = "";
String newUrl = originalUrl.replace("ID", name);
System.out.println(newUrl);
String request = newUrl;
URL url1 = new URL( request );
HttpURLConnection conn= (HttpURLConnection) url1.openConnection();
conn.setDoOutput( true );
conn.setInstanceFollowRedirects( false );
conn.setRequestMethod( "POST" );
conn.setRequestProperty( "Content-Type", "text/plain");
conn.setRequestProperty( "charset", "utf-8");
//conn.setRequestProperty( "Content-Length", Integer.toString( line ));
conn.setUseCaches( false );
try( DataOutputStream wr = new DataOutputStream( conn.getOutputStream())) {
wr.write(postData);
System.out.println("200 ok");
this is what i tried but i had post in text/plain but i want to post in key/value pair.
updated code
URL oracle = new URL("");
try (BufferedReader in = new BufferedReader(
new InputStreamReader(oracle.openStream()))) {
String inputLine1;
while ((inputLine1 = in.readLine()) != null) {
System.out.println(inputLine1);
com.eclipsesource.json.JsonObject object = Json.parse(inputLine1).asObject();
com.eclipsesource.json.JsonArray items = Json.parse(inputLine1).asObject().get("data").asArray();
for (JsonValue item : items) {
//System.out.println(item.toString());
String name = item.asObject().getString("id", "Unknown Item");
System.out.println(name);
String quantity = item.asObject().getString("url", "id");
// JSONArray jsonArray2 = new JSONArray(quantity);
System.out.println(quantity);
/* Platform.runLater(() ->{
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(HV1.class.getName()).log(Level.SEVERE, null, ex);
}*/
Img.load(quantity);
URL url;
InputStream is = null;
BufferedReader br;
String line;
url = new URL(quantity);
is = url.openStream(); // throws an IOException
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
System.out.println(line);
byte[] postData= line.getBytes( StandardCharsets.UTF_8 );
wb2.load(line);
String originalUrl = "";
String newUrl = originalUrl.replace("ID", name);
System.out.println(newUrl);
URL url1 = new URL(newUrl);
Map<String,Object> params = new LinkedHashMap<>();
params.put("content", postData);
params.put("meta", "abc");
StringBuilder postData1 = new StringBuilder();
for (Map.Entry<String,Object> param : params.entrySet()) {
if (postData1.length() != 0) postData1.append('&');
postData1.append(URLEncoder.encode(param.getKey(), "UTF-8"));
postData1.append('=');
postData1.append(URLEncoder.encode(String.valueOf(param.getValue()), "UTF-8"));
}
byte[] postDataBytes = postData1.toString().getBytes("UTF-8");
HttpURLConnection conn = (HttpURLConnection)url1.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", String.valueOf(postDataBytes.length));
conn.setDoOutput(true);
conn.getOutputStream().write(postDataBytes);
Reader in1 = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));
for (int c; (c = in1.read()) >= 0;)
System.out.print((char)c);
/* try{
Thread.sleep(400);
}catch(InterruptedException e){System.out.println(e);} */
}
}
}
this is my updted code(answer) this is how i solve my problem thanks for your precious time.
Take a look at this previous answer regarding HTTP Post parameters that exploit BasicNameValuePairs.
Name Value Pairs
Here is a pertinent piece of code from that answer.
HttpClient httpclient;
HttpPost httppost;
ArrayList<NameValuePair> postParameters;
httpclient = new DefaultHttpClient();
httppost = new HttpPost("your login link");
postParameters = new ArrayList<NameValuePair>();
postParameters.add(new BasicNameValuePair("param1", "param1_value"));
postParameters.add(new BasicNameValuePair("param2", "param2_value"));
httpPost.setEntity(new UrlEncodedFormEntity(postParameters, "UTF-8"));
HttpResponse response = httpclient.execute(httpPost);
Best would be using something like Spring and Jackson to create a JSON sending via a request, if you are not familiar with what you are trying to achieve:
This is just basic implementation
private final String uri = "yoururl.de/asdfasd";
private final HttpMethod httpMethod = HttpMethod.POST;
private final ContentType contentType = ContentType.json;
And EPO to transfer the Data
SendKeyValuePairsEPO implements Serializable{
private static final long serialVersionUID = 5311348008314829094L;
private final Integer startIndex;
private final Integer size;
private final Integer totalSize;
private final List<KeyValuePairEPO> values;
/**
* Contructor
*
* #param startIndex start searching index
* #param size requested result size
* #param totalSize total size of available records
* #param values the key value pairs
*/
public SendKeyValuePairsEPO(#JsonProperty("startIndex") final Integer startIndex,
#JsonProperty("size") final Integer size,
#JsonProperty("totalSize") final Integer totalSize,
#JsonProperty("values") final List<KeyValuePairEPO> values) {
this.startIndex = startIndex;
this.size = size;
this.totalSize = totalSize;
this.values = values;
}
and aswell a KeyValuePairEPO:
KeyValuePairEPO implements Serializable{
private static final long serialVersionUID = 5311348008314829094L;
private final String key;
private final String value;
private final String type; //maybe you need a type to tell what kind of value it is
...
And at last you will need to do something like:
/*package*/ <T> T sendRequest(Class<T> responseClass, Object requestEpo, String uri) {
try {
//Parse encapsulated COntent type to media type
HttpHeaders headers = new HttpHeaders();
MediaType requestContentType requestContentType = MediaType.APPLICATION_JSON;
//Set content type and accept header to this type
headers.setContentType(requestContentType);
headers.setAccept(Collections.singletonList(requestContentType));
//Parse the data object to a JSON
String requestJSONAsString = "";
if (request.getData() != null) {
try {
requestJSONAsString = RestObjectMapper.getInstance().writeValueAsString(requestEpo);
} catch (JsonProcessingException ex) {
throw new InternalServerErrorException(String.format("Error parsing: %s", requestEpo.getClass().getSimpleName()), ex);
}
}
//Perform the send request
return sendRequest(responseClass, uri, headers, httpMethod, requestJSONAsString);
} finally {
LOG.debug("Ended sendRequest");
}
}
private <T> T sendRequest(final Class<T> responseClass, final String uri, final HttpHeaders httpHeaders, final HttpMethod httpMethod, String requestJSON) {
try {
LOG.debug(String.format("Start sendRequest with:%s %s %s %s", uri, httpHeaders, httpMethod, requestJSON));
RestTemplate rest = new RestTemplate();
ClientHttpRequestFactory restFactory = rest.getRequestFactory();
if(restFactory instanceof SimpleClientHttpRequestFactory){
((SimpleClientHttpRequestFactory)restFactory).setReadTimeout(REQUEST_TIMEOUT);
((SimpleClientHttpRequestFactory)restFactory).setConnectTimeout(REQUEST_TIMEOUT);
}
HttpEntity<String> entity = new HttpEntity<>(requestJSON, httpHeaders);
final ResponseEntity<String> response = rest.exchange(uri, httpMethod, entity, String.class);
LOG.debug("Status:" + response.getStatusCode().toString());
String returnedPayload = response.getBody();
return RestObjectMapper.getInstance().readValue(returnedPayload, responseClass);
} catch (HttpStatusCodeException ex) {
LOG.error("HTTP Error in sendRequest: " + ex.getMessage());
switch (ex.getStatusCode()) {
case BAD_REQUEST:
throw new BadRequestException(uri, ex);
case NOT_FOUND:
throw new NotFoundException(uri, ex);
case FORBIDDEN:
throw new ForbiddenException(uri, ex);
case REQUEST_TIMEOUT:
throw new RequestTimeoutException(ex, REQUEST_TIMEOUT);
default:
throw new InternalServerErrorException(ex);
}
} catch (Exception ex) {
LOG.error("Error in sendRequest: " + ex.getMessage());
throw new InternalServerErrorException(ex);
} finally {
LOG.debug("Ended sendRequest");
}
}
where RestObjectMapper is:
public class RestObjectMapper extends ObjectMapper {
public static final String EMPTY_JSON = "{}";
private static final long serialVersionUID = 3924442982193452932L;
/**
* Singleton Instance
* Pattern: Initialization-on-demand holder idiom:
* <ul>
* <li>the class loader loads classes when they are first accessed (in this case Holder's only access is within the getInstance() method)</li>
* <li>when a class is loaded, and before anyone can use it, all static initializers are guaranteed to be executed (that's when Holder's static block fires)</li>
* <li>the class loader has its own synchronization built right in that make the above two points guaranteed to be threadsafe</li></ul>
*/
private static class INSTANCE_HOLDER {
private static final RestObjectMapper INSTANCE = new RestObjectMapper();
}
private RestObjectMapper() {
super();
configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true);
configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, true);
configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true);
configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true);
configure(DeserializationFeature.UNWRAP_ROOT_VALUE, false);
configure(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS, true);
setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
/**
* Gets the singleton Instance of the JSON Mapper
*
* #return the singleton instance
*/
public static RestObjectMapper getInstance() {
return INSTANCE_HOLDER.INSTANCE;
}
By the way ResponseClass is another EPO the result (JSON) will be mapped to.
I have a use case to authenticate OAuth1 request which is signed using RSA Private Key and verified at server end with RSA public key.
I found this library from Twitter which helps us authenticate/verify the Oauth signed requests. https://github.com/twitter/joauth
I want to leverage this library for verifying the request from Jersey or Spring MVC action method. The request from client would have been signed using private key. At my end I would use the public key of the client to verify the request. which means RSA-SHA1 algo.
Twitter joauth seem to be useful but I am missing the code that would transform HttpServletRequest to OAuthRequest
The library read-me file suggests this as facility but I could not find a code that does javax.servlet.http.HttpServletRequest --> com.twitter.joauth.OAuthRequest transformation.
The request verification happens in verify method which has following signature.
public VerifierResult verify(UnpackedRequest.OAuth1Request request, String tokenSecret, String consumerSecret);
Secondly I also want to know which is the most appropriate way to use/read RSA public key with twitter joauth when verify method takes String parameter ?
I have never used any library to authenticate users via Twitter. But I have just looked in the UnpackedRequest.OAuth1Request. You can create an instance of this class by filling all parameters. I have written Twitter OAuth Header creator, so you can just use it to fill those parameters or send POST requests directly without a library.
Here all classes what you need:
Signature - to generate an OAuth Signature.
public class Signature {
private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
public static String calculateRFC2104HMAC(String data, String key)
throws java.security.SignatureException
{
String result;
try {
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
byte[] rawHmac = mac.doFinal(data.getBytes());
result = new String(Base64.encodeBase64(rawHmac));
} catch (Exception e) {
throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
}
return result;
}
}
NvpComparator - to sort parameters you need in the header.
public class NvpComparator implements Comparator<NameValuePair> {
#Override
public int compare(NameValuePair arg0, NameValuePair arg1) {
String name0 = arg0.getName();
String name1 = arg1.getName();
return name0.compareTo(name1);
}
}
OAuth - for URL encode.
class OAuth{
...
public static String percentEncode(String s) {
return URLEncoder.encode(s, "UTF-8")
.replace("+", "%20").replace("*", "%2A")
.replace("%7E", "~");
}
...
}
HeaderCreator - to create all needed parameters and generate an OAuth header param.
public class HeaderCreator {
private String authorization = "OAuth ";
private String oAuthSignature;
private String oAuthNonce;
private String oAuthTimestamp;
private String oAuthConsumerSecret;
private String oAuthTokenSecret;
public String getAuthorization() {
return authorization;
}
public String getoAuthSignature() {
return oAuthSignature;
}
public String getoAuthNonce() {
return oAuthNonce;
}
public String getoAuthTimestamp() {
return oAuthTimestamp;
}
public HeaderCreator(){}
public HeaderCreator(String oAuthConsumerSecret){
this.oAuthConsumerSecret = oAuthConsumerSecret;
}
public HeaderCreator(String oAuthConsumerSecret, String oAuthTokenSecret){
this(oAuthConsumerSecret);
this.oAuthTokenSecret = oAuthTokenSecret;
}
public String getTwitterServerTime() throws IOException, ParseException {
HttpsURLConnection con = (HttpsURLConnection)
new URL("https://api.twitter.com/oauth/request_token").openConnection();
con.setRequestMethod("HEAD");
con.getResponseCode();
String twitterDate= con.getHeaderField("Date");
DateFormat formatter = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
Date date = formatter.parse(twitterDate);
return String.valueOf(date.getTime() / 1000L);
}
public String generatedSignature(String url, String method, List<NameValuePair> allParams,
boolean withToken) throws SignatureException {
oAuthNonce = String.valueOf(System.currentTimeMillis());
allParams.add(new BasicNameValuePair("oauth_nonce", oAuthNonce));
try {
oAuthTimestamp = getTwitterServerTime();
allParams.add(new BasicNameValuePair("oauth_timestamp", oAuthTimestamp));
}catch (Exception ex){
//TODO: Log!!
}
Collections.sort(allParams, new NvpComparator());
StringBuffer params = new StringBuffer();
for(int i=0;i<allParams.size();i++)
{
NameValuePair nvp = allParams.get(i);
if (i>0) {
params.append("&");
}
params.append(nvp.getName() + "=" + OAuth.percentEncode(nvp.getValue()));
}
String signatureBaseStringTemplate = "%s&%s&%s";
String signatureBaseString = String.format(signatureBaseStringTemplate,
OAuth.percentEncode(method),
OAuth.percentEncode(url),
OAuth.percentEncode(params.toString()));
String compositeKey = OAuth.percentEncode(oAuthConsumerSecret)+"&";
if(withToken) compositeKey+=OAuth.percentEncode(oAuthTokenSecret);
oAuthSignature = Signature.calculateRFC2104HMAC(signatureBaseString, compositeKey);
return oAuthSignature;
}
public String generatedAuthorization(List<NameValuePair> allParams){
authorization = "OAuth ";
Collections.sort(allParams, new NvpComparator());
for(NameValuePair nvm : allParams){
authorization+=nvm.getName()+"="+OAuth.percentEncode(nvm.getValue())+", ";
}
authorization=authorization.substring(0,authorization.length()-2);
return authorization;
}
}
Explain:
1. getTwitterServerTime
In oAuthTimestamp you need not your time of server but the time of a Twitter server. You can optimize it saving this param if you always send requests in the certain Twitter server.
2. HeaderCreator.generatedSignature(...)
url - logically url to twitter API
method - GET or POST. You must use always "POST"
allParams - Parameters which you know to generate signature ("param_name", "param_value");
withToken - if you know oAuthTokenSecret put true. Otherwise false.
3. HeaderCreator.generatedAuthorization(...)
Use this method after generatedSignature(...) to generate an OAuth header string.
allParams - it is parameters which you have used in generatedSignature(...) plus: nonce, signature, timestamp. Always use:
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
Now you can use it to fill UnpackedRequest.OAuth1Request in your library. Also here an example to authenticate user in SpringMVC without the library:
Requests - to send post requests.
public class Requests {
public static String sendPost(String url, String urlParameters, Map<String, String> prop) throws Exception {
URL obj = new URL(url);
HttpsURLConnection con = (HttpsURLConnection) obj.openConnection();
con.setRequestMethod("POST");
if(prop!=null) {
for (Map.Entry<String, String> entry : prop.entrySet()) {
con.setRequestProperty(entry.getKey(), entry.getValue());
}
}
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
int responseCode = con.getResponseCode();
BufferedReader in;
if(responseCode==200) {
in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
}else{
in = new BufferedReader(
new InputStreamReader(con.getErrorStream()));
}
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
return response.toString();
}
}
twAuth(...) - put it in your controller. Execute it when an user want to authenticate in your site via Twitter.
#RequestMapping(value = "/twauth", method = RequestMethod.GET)
#ResponseBody
public String twAuth(HttpServletResponse response) throws Exception{
try {
String url = "https://api.twitter.com/oauth/request_token";
List<NameValuePair> allParams = new ArrayList<NameValuePair>();
allParams.add(new BasicNameValuePair("oauth_callback", "http://127.0.0.1:8080/twlogin"));
allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT"));
allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1"));
allParams.add(new BasicNameValuePair("oauth_version", "1.0"));
HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL");
headerCreator.generatedSignature(url,"POST",allParams,false);
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
Map<String, String> props = new HashMap<String, String>();
props.put("Authorization", headerCreator.generatedAuthorization(allParams));
String twitterResponse = Requests.sendPost(url,"",props);
Integer indOAuthToken = twitterResponse.indexOf("oauth_token");
String oAuthToken = twitterResponse.substring(indOAuthToken, twitterResponse.indexOf("&",indOAuthToken));
response.sendRedirect("https://api.twitter.com/oauth/authenticate?" + oAuthToken);
}catch (Exception ex){
//TODO: Log
throw new Exception();
}
return "main";
}
twLogin(...) - put it in your controller. It is callback from Twitter.
#RequestMapping(value = "/twlogin", method = RequestMethod.GET)
public String twLogin(#RequestParam("oauth_token") String oauthToken,
#RequestParam("oauth_verifier") String oauthVerifier,
Model model, HttpServletRequest request){
try {
if(oauthToken==null || oauthToken.equals("") ||
oauthVerifier==null || oauthVerifier.equals(""))
return "main";
String url = "https://api.twitter.com/oauth/access_token";
List<NameValuePair> allParams = new ArrayList<NameValuePair>();
allParams.add(new BasicNameValuePair("oauth_consumer_key", "2YhNLyum1VY10UrWBMqBnatiT"));
allParams.add(new BasicNameValuePair("oauth_signature_method", "HMAC-SHA1"));
allParams.add(new BasicNameValuePair("oauth_token", oauthToken));
allParams.add(new BasicNameValuePair("oauth_version", "1.0"));
NameValuePair oAuthVerifier = new BasicNameValuePair("oauth_verifier", oauthVerifier);
allParams.add(oAuthVerifier);
HeaderCreator headerCreator = new HeaderCreator("RUesRE56vVWzN9VFcfA0jCBz9VkvkAmidXj8d1h2tS5EZDipSL");
headerCreator.generatedSignature(url,"POST",allParams,false);
allParams.add(new BasicNameValuePair("oauth_nonce", headerCreator.getoAuthNonce()));
allParams.add(new BasicNameValuePair("oauth_signature", headerCreator.getoAuthSignature()));
allParams.add(new BasicNameValuePair("oauth_timestamp", headerCreator.getoAuthTimestamp()));
allParams.remove(oAuthVerifier);
Map<String, String> props = new HashMap<String, String>();
props.put("Authorization", headerCreator.generatedAuthorization(allParams));
String twitterResponse = Requests.sendPost(url,"oauth_verifier="+oauthVerifier,props);
//Get user id
Integer startIndexTmp = twitterResponse.indexOf("user_id")+8;
Integer endIndexTmp = twitterResponse.indexOf("&",startIndexTmp);
if(endIndexTmp<=0) endIndexTmp = twitterResponse.length()-1;
Long userId = Long.parseLong(twitterResponse.substring(startIndexTmp, endIndexTmp));
//Do what do you want...
}catch (Exception ex){
//TODO: Log
throw new Exception();
}
}
I have these methods in a class called HttpHelper. Now the initial call validates user credentials and returns true. That is expected. The next call is to register a user. That seems to go fine with no hiccups and is to return the new user ID. Instead of returning the user ID it returns true again. Almost like it is cached and just returning the result from the initial call. Anyone have any thoughts as to why this might occur?
private static CookieStore sCookieStore;
private static String invoke(HttpUriRequest request)
throws ClientProtocolException, IOException {
String result = null;
DefaultHttpClient httpClient = new DefaultHttpClient();
// restore cookie
if (sCookieStore != null) {
httpClient.setCookieStore((org.apache.http.client.CookieStore) sCookieStore);
}
//request.addHeader("Host", "localhost");
HttpResponse response = httpClient.execute(request);
StringBuilder builder = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent()));
for (String s = reader.readLine(); s != null; s = reader.readLine()) {
builder.append(s);
}
result = builder.toString();
Log.d(TAG, "result is ( " + result + " )");
// store cookie
sCookieStore = (CookieStore) ((AbstractHttpClient) httpClient).getCookieStore();
return result;
}
public static String invokeGet(String action, List<NameValuePair> params) {
try {
StringBuilder sb = new StringBuilder(API_URL);
sb.append(action);
if (params != null) {
for (NameValuePair param : params) {
sb.append("?");
sb.append(param.getName());
sb.append("=");
sb.append(param.getValue());
}
}
Log.d(TAG, "url is" + sb.toString());
//HttpGet httpGet = new HttpGet(URLEncoder.encode(sb.toString(), "UTF-8"));
HttpGet httpGet = new HttpGet(sb.toString());
return invoke(httpGet);
} catch (Exception e) {
Log.e(TAG, e.toString());
}
return null;
}
public static String invokeGet(String action) {
return invokeGet(action, null);
}
Here are the calls I am making. As specified above the authResult variable would result in a string result of true. The nextResult should hold the user ID value but instead holds the value true like from the initial request:
String authResult = HttpHelper.invokeGet("<url to validate user>");
if (this.URL.indexOf("register") > -1)
String nextResult = HttpHelper.invokeGet(this.URL);
else
String nextResult = HttpHelper.invokeGet(this.URL);
UPDATED: added in the sCookieStore variable.
UPDATED 2: adding in the methods that are being called via the API (MVC .NET):
authResult variable would get this result:
public bool Get(String userName, String userPassword)
{
Task<IdentityUser> iu = _repo.FindUser(userName, userPassword);
if (iu != null)
{
FormsAuthentication.SetAuthCookie(userName, false);
return true;
}
return false;
}
nextResult variable should get this result:
[HttpGet]
[AllowAnonymous]
public async Task<IHttpActionResult> RegisterUser(String userName, String userPassword, String huh)
{
UserModel userModel = new UserModel();
userModel.ConfirmPassword = userPassword;
userModel.UserName = userName;
userModel.Password = userPassword;
String userID = "";
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
IdentityResult result = await _repo.RegisterUser(userModel);
IHttpActionResult errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
else
{
Task<IdentityUser> iu = _repo.FindUser(userModel.UserName, userModel.Password);
using (var context = new AuthContext())
{
var userStore = new UserStore<IdentityUser>(context);
var userManager = new UserManager<IdentityUser>(userStore);
userID = iu.Result.Id;
result = await userManager.AddToRoleAsync(userID, "Users");
errorResult = GetErrorResult(result);
if (errorResult != null)
{
return errorResult;
}
}
}
return Ok("userID:" + userID);
}
It looks like authResult is going to fire invokeGet 2 times, giving it the same argument (this.URL). Within invokeGet, the variable sb is going to be this.URL both times the function fires.
This is a bit curious to me:
// restore cookie
if (sCookieStore != null) {
httpClient.setCookieStore((org.apache.http.client.CookieStore) sCookieStore);
}
then at the end,
// store cookie
sCookieStore = (CookieStore) ((AbstractHttpClient) httpClient).getCookieStore();
When is sCookieStore defined? It could be that the cookies aren't being handled correctly and you're making two fresh connections. If getting and setting the cookies is the issue, it might be better to get a cookie if it exists at the beginning of invoke, then set the new one at the end.
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;
}