how to post data in key/value pair? [duplicate] - java

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.

Related

Data fetching from an API in android

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();

What is proper practice for multithreading and httpclient in Java?

I'm creating a program that can do multiple logins. I will also give each login the ability to add an item to cart and purchase. The code is currently working for one account, and it's very basic. I had to trim out some private information, but the code should still be clear. Again, I'm just wondering what approach I should take for multiple logins? Does this code for the most part look optimal for speed? How do I approach a retry attempt if checkout returns 500? This code is currently setup for only a single login. Also, there weren't many articles I found to properly clean up the HttpClient. At least, I don't think the tutorials I found were very reputable.
Thanks again for taking the time to read this, I just want to learn other practices to improve my code and approach a proper multithreading technique.
Alittle more detail about my code, there is a token that is retrieved when you view the page, the token is stored and used throughout the program.
class example {
private static List<Header> headers = new ArrayList<Header>();
private static BasicCookieStore cookieStore = new BasicCookieStore();
private static CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultHeaders(headers).setDefaultCookieStore(cookieStore).build();
public static void main(String[] args) throws Exception {
String loginURL = "...";
String productUrl = "...";
String userid = "";
String password = "";
String formKey = "";
int size = 9;
Boolean debug = true;
JsonElement product;
headers.add(new BasicHeader("Host", "..."));
headers.add(new BasicHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"));
headers.add(new BasicHeader("Accept-Language", "en-us"));
headers.add(new BasicHeader("Content-Encoding", "gzip, deflate"));
headers.add(new BasicHeader("Content-Type", "Application/x-www-form-urlencoded"));
headers.add(new BasicHeader("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 8_4_1 like Mac OS X) "
+ "AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H321 Safari/600.1.4"));
headers.add(new BasicHeader("Connection", "keep-alive"));
Scanner in = new Scanner(System.in);
Gson gson = new Gson();
System.out.println("Select Profile\n1. ...\n2. Custom");
int select = in.nextInt();
switch(select) {
case 1:
userid = "...";
password = "...";
break;
// Custom Account Login
case 2:
System.out.println("Enter User_ID:");
userid = in.next();
System.out.println("Enter Password:");
password = in.next();
break;
}
int input = 0;
do {
input = in.nextInt();
switch(input) {
case 99:
debug = true;
break;
// View Menu.
case 0:
System.out.println("...");
break;
// Initiate Session
case 1:
// Retrieve formKey for login page.
formKey = getLogin(GetPageContent(loginURL));
session(formKey, userid, password, debug);
System.out.println("Press 0 to View Menu");
break;
case 2:
product = getProduct(GetPageContent(productUrl));
// Retrieve Product ID
Product productInfo = gson.fromJson(product.getAsJsonObject(), Product.class);
// Retrieve Color
Product[] color = gson.fromJson(product.getAsJsonObject().getAsJsonObject("attributes").getAsJsonObject("92").getAsJsonArray("options"), Product[].class);
// Prepare product request
String productKey = productInfo.getProductId();
String colorId = color[0].getId();
String postUrl = productInfo.getPostUrl();
// Execute addToCart
String result = addToCart(formKey, postUrl, productKey, colorId, size, debug);
break;
case 3:
String result2 = checkout(formKey);
break;
}
} while(input != 0);
}
public static void session(String formKey, String userid, String password, Boolean debug) {
HttpPost post = new HttpPost("...");
try {
// Package the data
StringEntity entity = new StringEntity("...");
post.setEntity(entity);
// Execute the data
HttpResponse response = httpClient.execute(post);
} catch (Exception e) {
e.printStackTrace();
} finally {
post.releaseConnection();
System.out.println("Login execution completed.");
}
}
public static String addToCart(String formKey, String postUrl, String productId, String colorId, int size, Boolean debug) {
String result = "";
HttpPost post = new HttpPost(postUrl);
try {
StringEntity entity = new StringEntity("...");
post.setEntity(entity);
// Execute the data
HttpResponse response = httpClient.execute(post);
System.out.println("Response Code : "
+ response.getStatusLine().getStatusCode());
// RETURN RESULT
result = EntityUtils.toString(response.getEntity());
if(debug) {
System.out.println("LOG: " + result);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
post.releaseConnection();
System.out.println("Adding to cart execution completed.");
}
return result;
}
public static String GetPageContent(String url) throws Exception {
StringBuffer result = null;
HttpGet request = new HttpGet(url);
try {
HttpResponse response = httpClient.execute(request);
int responseCode = response.getStatusLine().getStatusCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader rd = new BufferedReader(
new InputStreamReader(response.getEntity().getContent()));
result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
result.append(line);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
request.releaseConnection();
}
return result.toString();
}
public static String getLogin(String html) {
String formKey = "";
Document doc = Jsoup.parse(html);
Element loginform = doc.getElementById("login-form");
Elements inputElements = loginform.getElementsByTag("input");
for (Element inputElement : inputElements) {
String key = inputElement.attr("name");
String value = inputElement.attr("value");
if (key.equals("form_key"))
formKey = value;
}
return formKey;
}
public static JsonObject getProduct(String html)
throws UnsupportedEncodingException {
Document doc = Jsoup.parse(html);
System.out.println("Extracting form's data...");
Element form = doc.getElementById("product_addtocart_form");
Elements formElements = form.getElementsByTag("input");
String rawScript = form.getElementsByTag("script").html();
String script = "{" + rawScript.substring(rawScript.lastIndexOf("g({") + 3, rawScript.indexOf("}});")) + "}}";
// Create JSON object
JsonElement jelement = new JsonParser().parse(script.trim());
JsonObject jobject = jelement.getAsJsonObject();
jobject = jobject.getAsJsonObject();
// Retrieve post link.
jobject.addProperty("postUrl", form.attr("action"));
return jobject;
}
public static String checkout(String formKey) {
HttpPost post = new HttpPost("...");
String result = "";
try {
StringEntity entity = new StringEntity("...");
post.setEntity(entity);
HttpResponse response = httpClient.execute(post);
int status = response.getStatusLine().getStatusCode();
if(status == 200) {
result = EntityUtils.toString(response.getEntity());
System.out.println("Checkout Result: " + result);
} else if(status == 302) {
System.out.println("Checkout failed, Code: 302.");
} else if(status == 404) {
System.out.println("Checkout failed, Code: 404.");
} else if(status == 500) {
(insert retry step here)
System.out.println("Webserver is probably down. Code, 500.");
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
post.releaseConnection();
}
return result;
}
}

Verify OAuth1a signed request using Twitter joauth with RSA-SHA1?

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();
}
}

Sending Complex JSON Object

I want to communicate with a web server and exchange JSON information.
my webservice URL looking like following format: http://46.157.263.140/EngineTestingWCF/DPMobileBookingService.svc/SearchOnlyCus
Here is my JSON Request format.
{
"f": {
"Adults": 1,
"CabinClass": 0,
"ChildAge": [
7
],
"Children": 1,
"CustomerId": 0,
"CustomerType": 0,
"CustomerUserId": 81,
"DepartureDate": "/Date(1358965800000+0530)/",
"DepartureDateGap": 0,
"Infants": 1,
"IsPackageUpsell": false,
"JourneyType": 2,
"PreferredCurrency": "INR",
"ReturnDate": "/Date(1359138600000+0530)/",
"ReturnDateGap": 0,
"SearchOption": 1
},
"fsc": "0"
}
I tried with the following code to send a request:
public class Fdetails {
private String Adults = "1";
private String CabinClass = "0";
private String[] ChildAge = { "7" };
private String Children = "1";
private String CustomerId = "0";
private String CustomerType = "0";
private String CustomerUserId = "0";
private Date DepartureDate = new Date();
private String DepartureDateGap = "0";
private String Infants = "1";
private String IsPackageUpsell = "false";
private String JourneyType = "1";
private String PreferredCurrency = "MYR";
private String ReturnDate = "";
private String ReturnDateGap = "0";
private String SearchOption = "1";
}
public class Fpack {
private Fdetails f = new Fdetails();
private String fsc = "0";
}
Then using Gson I create the JSON object like:
public static String getJSONString(String url) {
String jsonResponse = null;
String jsonReq = null;
Fpack fReq = new Fpack();
try {
Gson gson = new Gson();
jsonReq = gson.toJson(fReq);
JSONObject json = new JSONObject(jsonReq);
JSONObject jsonObjRecv = HttpClient.SendHttpPost(url, json);
jsonResponse = jsonObjRecv.toString();
}
catch (JSONException e) {
e.printStackTrace();
}
return jsonResponse;
}
and my HttpClient.SendHttpPost method is
public static JSONObject SendHttpPost(String URL, JSONObject json) {
try {
DefaultHttpClient httpclient = new DefaultHttpClient();
HttpPost httpPostRequest = new HttpPost(URL);
StringEntity se;
se = new StringEntity(json.toString());
httpPostRequest.setEntity(se);
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
HttpResponse response = (HttpResponse) httpclient.execute(httpPostRequest);
HttpEntity entity = response.getEntity();
if (entity != null) {
// Read the content stream
InputStream instream = entity.getContent();
Header contentEncoding = response.getFirstHeader("Content-Encoding");
if (contentEncoding != null && contentEncoding.getValue().equalsIgnoreCase("gzip")) {
instream = new GZIPInputStream(instream);
}
// convert content stream to a String
String resultString= convertStreamToString(instream);
instream.close();
resultString = resultString.substring(1,resultString.length()-1); // remove wrapping "[" and "]"
// Transform the String into a JSONObject
JSONObject jsonObjRecv = new JSONObject(resultString);
return jsonObjRecv;
}
catch (Exception e)
{
e.printStackTrace();
}
return null;
}
Now I get the following exception:
org.json.JSONException: Value !DOCTYPE of type java.lang.String cannot be converted to JSONObject
at org.json.JSON.typeMismatch(JSON.java:111)
at org.json.JSONObject.<init>(JSONObject.java:158)
at org.json.JSONObject.<init>(JSONObject.java:171)
and the printout of JSON string right before I make the request is as follows:
{
"f": {
"PreferredCurrency": "MYR",
"ReturnDate": "",
"ChildAge": [
7
],
"DepartureDate": "Mar 2, 2013 1:17:06 PM",
"CustomerUserId": 0,
"CustomerType": 0,
"CustomerId": 0,
"Children": 1,
"DepartureDateGap": 0,
"Infants": 1,
"IsPackageUpsell": false,
"JourneyType": 1,
"CabinClass": 0,
"Adults": 1,
"ReturnDateGap": 0,
"SearchOption": 1
},
"fsc": "0"
}
How do I solve this exception? Thanks in advance!
To create a request with JSON object attached to it what you should do is the following:
public static String sendComment (String commentString, int taskId, String sessionId, int displayType, String url) throws Exception
{
Map<String, Object> jsonValues = new HashMap<String, Object>();
jsonValues.put("sessionID", sessionId);
jsonValues.put("NewTaskComment", commentString);
jsonValues.put("TaskID" , taskId);
jsonValues.put("DisplayType" , displayType);
JSONObject json = new JSONObject(jsonValues);
DefaultHttpClient client = new DefaultHttpClient();
HttpPost post = new HttpPost(url + SEND_COMMENT_ACTION);
AbstractHttpEntity entity = new ByteArrayEntity(json.toString().getBytes("UTF8"));
entity.setContentType(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
post.setEntity(entity);
HttpResponse response = client.execute(post);
return getContent(response);
}
I'm not quite familiar with Json, but I know it's pretty commonly used today, and your code seems no problem.
How to convert this JSON string to JSON object?
Well, you almost get there, just send the JSON string to your server, and use Gson again in your server:
Gson gson = new Gson();
Fpack f = gson.fromJSON(json, Fpack.class);
http://google-gson.googlecode.com/svn/trunk/gson/docs/javadocs/index.html
About the Exception:
You should remove this line, because you are sending a request, not responsing to one:
httpPostRequest.setHeader("Accept", "application/json");
And I would change this line:
httpPostRequest.setHeader("Content-type", "application/json");
to
se.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE, "application/json"));
If this doesn't make any difference, please print out your JSON string before you send the request, let's see what's in there.
From what I have understood you want to make a request to the server using the JSON you have created, you can do something like this:
URL url;
HttpURLConnection connection = null;
String urlParameters ="json="+ jsonSend;
try {
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded");
connection.setRequestProperty("Content-Language", "en-US");
DataOutputStream wr = new DataOutputStream (
connection.getOutputStream ());
wr.writeBytes (urlParameters);
wr.flush ();
wr.close ();
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
while((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if(connection != null) {
connection.disconnect();
}
}
}
Actually it was a BAD REQUEST. Thats why server returns response as XML format.
The problem is to convert the non primitive data(DATE) to JSON object.. so it would be Bad Request..
I solved myself to understand the GSON adapters.. Here is the code I used:
try {
JsonSerializer<Date> ser = new JsonSerializer<Date>() {
#Override
public JsonElement serialize(Date src, Type typeOfSrc,
JsonSerializationContext comtext) {
return src == null ? null : new JsonPrimitive("/Date("+src.getTime()+"+05300)/");
}
};
JsonDeserializer<Date> deser = new JsonDeserializer<Date>() {
#Override
public Date deserialize(JsonElement json, Type typeOfT,
JsonDeserializationContext jsonContext) throws JsonParseException {
String tmpDate = json.getAsString();
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(tmpDate);
boolean found = false;
while (matcher.find() && !found) {
found = true;
tmpDate = matcher.group();
}
return json == null ? null : new Date(Long.parseLong(tmpDate));
}
};

commons httpclient - Adding query string parameters to GET/POST request

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;
}

Categories