I am pretty new concerning REST api and POST request.
I have the url of a REST api. I need to access to this api by doing an API call in JAVA thanks to a client id and a client secret (I found a way to hash the client secret). However, as I am new I don't know how to do that api call. I did my research during this all day on internet but I found no tutorial, website or anything else about how to do an api call. So please, does anyone know a tutorial or how to do that? (if you also have something about POST request it would be great)
I would be very thankful.
Thank you very much for your kind attention.
Sassir
Here's a basic example snippet using JDK classes only. This might help you understand HTTP-based RESTful services a little better than using a client helper. The order in which you call these methods is crucial. If you have issues, add a comments with your issue and I will help you through it.
URL target = new URL("http://www.google.com");
HttpURLConnectionconn = (HttpURLConnection) target.openConnection();
conn.setRequestMethod("GET");
// used for POST and PUT, usually
// conn.setDoOutput(true);
// OutputStream toWriteTo = conn.getOutputStream();
conn.connect();
int responseCode = conn.getResponseCode();
try
{
InputStream response = conn.getInputStream();
}
catch (IOException e)
{
InputStream error = conn.getErrorStream();
}
You can also use RestTemplate from Spring: https://spring.io/blog/2009/03/27/rest-in-spring-3-resttemplate
Fast and simple solution without any boilerplate code.
Simple example:
RestTemplate rest = new RestTemplate();
MultiValueMap<String, String> map = new LinkedMultiValueMap<String, String>();
map.add("firstParamater", "parameterValue");
map.add("secondParameter", "differentValue");
rest.postForObject("http://your-rest-api-url", map, String.class);
The Restlet framework also allows you to do such thing thanks to its class ClientResource. In the code below, you build and send a JSON content within the POST request:
ClientResource cr = new ClientResource("http://...");
SONObject jo = new JSONObject();
jo.add("entryOne", "...");
jo.add("entryTow", "...");
cr.post(new JsonRepresentation(jo), MediaType.APPLICATION_JSON);
Restlet allows to send any kind of content (JSON, XML, YAML, ...) and can also manage the bean / representation conversion for you using its converter feature (creation of the representation based on a bean - this answer gives you more details: XML & JSON web api : automatic mapping from POJOs?).
You can also note that HTTP provides an header Authorization that allows to provide authentication hints for a request. Several technologies are supported here: basic, oauth, ... This link could help you at this level: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/.
Using authentication (basic authentication for example) can be done like this:
String username = (...)
String password = (...)
cr.setChallengeResponse(ChallengeScheme.HTTP_BASIC, username, password);
(...)
cr.post(new JsonRepresentation(jo), MediaType.APPLICATION_JSON);
Hope it helps you,
Thierry
Related
I'm using AsyncHttpClient library to make HTTP requests from a very basic Android app. For now, I just need to make a POST request with a JSON body (and that's a mandatory constraint, since the REST services I have to use expect a request in that format) containing a username and a password.
Not knowing much about Android development and the library in question I tried to make a simple GET request to Google, and it perfectly worked. Then, I tried to switch to a POST request but it seems from the documentation that the post method needs strictly a RequestParams parameter.
I really need to send a JSON: is there a way to do so with AsyncHttpClient? I tried several solutions found both on the web and on StackOverflow, but unfortunately no one worked.
Ultimately, as a last chance, I'm willing to switch library (and suggestions in this direction would be welcome, too - at least if they're easy-to-use as AsyncHttpClient is, considering my inexperience), but I would prefer to stick to my current choice.
Thanks for your help.
first, i suggest u to use retrofit library, it's simple, useful and sweet
but for now, we should to know that how do you do your post,
for example, do you test this:
private static AsyncHttpClient client = new AsyncHttpClient();
RequestParams params = new RequestParams();
params.put("param1", "Test");
client.post(Url, params, responseHandler);
JSONObject jsonParams = new JSONObject();
jsonParams.put("param1", "Test");
StringEntity entity = new StringEntity(jsonParams.toString());
client.post(context, Url, entity, "application/json",responseHandler);
Using java, when I expose some web service with Soap, I have a WSDL which describes all input/output, and if I use this WSDL in my SoapUI client, it will analyze it and generate some sample request for me.
What is the process to do this with Rest/Json. I know about wadl, but SoapUI can't generate sample request from this. I know about third party tools like Swagger suite, but is this the only way ? Do u have to use some external documentation tool to expose your API and show users some sample requests ?
There is no answer yet, so here is one a few years later.
You need to use OpenAPI Specification (let's call the result a "Swagger contract"), which defines a standard, language-agnostic interface to RESTful APIs and just forget about WADL.
This will be the equivalent of a SOAP WSDL, but easier to read , easier to produce, and lighter in constraints.
With Swagger, you can work in "Contract first" (using https://editor.swagger.io/ to design the contract) or in "Code first", where you will use frameworks like Springfox to generate the swagger contract from code + annotations. The last one is much easier imo, and it's just a different way of doing "contract first", it's not like if u were implementing the whole application before designing the contract.
Once you have the "swagger contract" document available on an URL, you can deploy a swagger-ui website to visualize it in an interactive way : it will generate some sample requests and will allow you to execute these requests after customizing them.
try {
url="put your service url";
HttpPost request = new HttpPost(url);
request.setHeader("Accept", "application/json");
request.setHeader("Content-type", "application/json");
// Build JSON string
JSONStringer item = new JSONStringer()
.object()
.key("password").value(pass)
.key("username").value(email)
.endObject();
StringEntity entity = new StringEntity(item.toString());
request.setEntity(entity);
// Send request to WCF service
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpResponse response = httpClient.execute(request);
HttpEntity entity1 = response.getEntity();
InputStream stream = entity1.getContent();
r = Splash.convertStreamToString(stream);
JSONObject jo = new JSONObject(r);
s= (Integer) jo.get("Flag");
Log.d("json result is:", r);
statusCode = response.getStatusLine().getStatusCode();
} catch (Exception e) {
e.printStackTrace();
Log.d("error", "code"+0);
}
return s;
}
Iam creating automated system to post the data to the form for registering into the web site
URL url = new URL("https://www.walmart.com/subflow/YourAccountLoginContext/1471476370/sub_generic_login/create_account.do");
String postData = "firstName="+xlsDataList.get(0)+"&lastName="+xlsDataList.get(1)+"&userName="+xlsDataList.get(2)+"&userNameConfirm="+xlsDataList.get(3)+"&pwd="+xlsDataList.get(5)+"&pwdConfirm="+xlsDataList.get(6);
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();
uc.setDoInput(true);
uc.setDoOutput(true);
uc.setRequestMethod("POST");
uc.setRequestProperty("Accept", "*/*");
uc.setRequestProperty("Content-Length", Integer.toString(postData.getBytes().length));
uc.setRequestProperty("Content-Type", "text/html; charset=utf-8");
OutputStreamWriter outputWriter = new OutputStreamWriter(uc.getOutputStream());
outputWriter.write(postData);
outputWriter.flush();
outputWriter.close();
I thought that those above postdata are just request attributes , and coded accordingly. But after closely checking the view source, i came to know that those are form attributes.
I dnt have access to that form. Now how can i post the data to the form, so that the user get registered by the site?
i have to set the values to formbean.
Please provide your suggesions.
Your are using the wrong Content-Type in your POST: you need to use application/x-www-form-urlencoded. Once you change that, the server will interpret your request body as request parameters and (likely) your "formbean" will be filled with the data.
The above code may be a test case, but you really ought to take care to properly encode all of your data that you are trying to POST. Otherwise, you run the risk of either having a syntactically invalid request (in which case, the server will either reject the request, or ignore important parameters) or introducing a security vulnerability where a user can inject arbitrary request parameters into your POST. I highly recommend code that looks like this:
import java.net.URLEncoder;
String charset = "UTF-8"; // Change this if you want some other encoding
StringBuilder postData = new StringBuilder();
postData.append(URLEncoder.encode("firstName", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(0)), charset);
postData.append("&");
postData.append(URLEncoder.encode("lastName", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(1), charset));
postData.append("&");
postData.append(URLEncoder.encode("userName", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(2), charset));
postData.append("&");
postData.append(URLEncoder.encode("userNameConfirm", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(3), charset));
postData.append("&");
postData.append(URLEncoder.encode("pwd", charset));
postData.append("=");
postData.append(URLEncoder.encode(xlsDataList.get(5), charset));
postData.append("&");
postData.append(URLEncoder.encode("pwdConfirm", charset));
postData.append("=");
postData.append(xlsDataList.get(6), charset));
It seems silly to encode the static strings like "userNameConfirm", but if you get into that habit, you'll end up using it all the time and your code will be a lot safer.
Also, you need to make sure that the data you send through the OutputStream has the right Content-Length: you are computing the content-length properly, but then you aren't using the bytes you used for the computation to send to the client. You want your code to look more like this:
byte[] postDataBytes = postData.getBytes(charset);
uc.setRequestProperty("Content-Length", Integer.toString(postDataBytes.length));
uc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
OutputStream outputStream = uc.getOutputStream();
outputStream.write(postDataBytes);
outputStream.flush();
outputStream.close();
You can find a very comprehensive HTTPUrlConnection tutorial in the community wiki: Using java.net.URLConnection to fire and handle HTTP requests
I recommend to use Apache HttpClient. its faster and easier to implement.
PostMethod post = new PostMethod("https://www.walmart.com/subflow/YourAccountLoginContext/1471476370/sub_generic_login/create_account.do");
NameValuePair[] data = {
new NameValuePair("firstName", "joe"),
new NameValuePair("lastName", "bloggs")
};
post.setRequestBody(data);
InputStream in = post.getResponseBodyAsStream();
// handle response.
For details you can refer http://hc.apache.org/
If your project uses Spring 3.x or later I would recommend using the Spring RestTemplate its pretty handy for doing http, code below will log do a form post.
public String login(String username, String password)
{
MultiValueMap<String, String> form = new LinkedMultiValueMap<>();
form.add(usernameInputFieldName, username);
form.add(passwordInputFieldName, password);
RestTemplate template = new RestTemplate();
URI location = template.postForLocation(loginUrl(), form);
return location.toString();
}
The "HTTP Error 500" you've described in your comment is an "Internal server error".
This means that the server either can't use your request (GET/POST) or there's a problem specific to the server you are trying to call.
Taking a look at the URL you're calling, I immediately the same Error 500.
Same happens for both GET and POST requests at httqs://www.walmart.com/subflow/YourAccountLoginContext/1471476370/sub_generic_login/create_account.do (Live link deactivated; replace "q" with "p" to make it work.)
In short: the generally returned "HTTP Error 500" from WallMart's servers prevents your call to succeed.
By the way:
It's not uncommon to get an error 500 instead of a 403 if they are locking your access down.
As you probably don't own the WallMart website and since you're trying to access levels of their websites that are worth to be protected from 3rd party acces, this might well be the case. ;)
PS: I'm not sure if it's wise to show the AccountLogin number in public like this. After all, it's the client ID of a specific WallMart account holder. But hey, that's your choice, not mine.
Also, double check the parameters you are sending. There may be some validations on input data the server is doing. Eg, some fields are mandatory, some are numbers only, etc.
Try spoofing as a browser by modifying the User Agent. WalMart may have a security mechanism that detects that you are doing this in an automated way.
(If you have problems setting the user agent see this post: Setting user agent of a java URLConnection)
I am developing a very simple http bot. I am using the javax.net.ssl.HttpsURLConnection class and I have to make multiple requests.
Snippet of code :
HttpURLConnection urlConnection =
(HttpURLConnection) new URL(url+"?"+firstParameters).openConnection();
urlConnection.setRequestProperty("Accept-Charset", "UTF-8");
headerFields = urlConnection.getHeaderFields();
keys = headerFields.keySet();
for(String key : keys){
if(key != null && key.contains("ookie")){
cookies = urlConnection.getHeaderField(key);
break;
}
}
for(String cookie : cookies.split(";")){
if(cookie.contains("JSESSION")){
JSESSION = cookie.split("=")[1];
break;
}
}
document = new InputSource(urlConnection.getInputStream());
parser.setDocument(document);
attributesId.put("name",new ArrayList<String>(Arrays.asList(attributesNames)));
elementsIds.put("INPUT",attributesId);
elements = parser.getValues(elementsIds);
for(String attr : attributesNames){
secondParameters = secondParameters.replaceAll("#r"+index,elements.get(attr));
}
urlConnection.getInputStream().close();
//Second call
urlConnection = (HttpURLConnection) new URL(url2).openConnection();
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Cookie", "JSESSIONID="+JSESSION);
urlConnection.setDoInput(true);
urlConnection.setDoOutput(true);
payload = new PrintWriter(urlConnection.getOutputStream());
payload.print(secondParameters);
payload.flush();
payload.close();
Summarizing the code above, first i do a request without any payload and i am able to see the correct response from the server, but the problem is when i make the second request (now with payload and with the JSESSION cookie), what i receive it his the same response that i received in the first request, it looks like i am making the first request again.
So my question is , what i am doing wrong ?
I just need to open one connection, and then change the headers and payload ?
There is any tutorial related with multiple http requests(with mixed methods , post and get)?
Thanks in advance
I've never used HttpURLConnection before. I usually use Apache's HTTPClient code. There are a lot of docs and tutorials about it on their home page.
Couple of things that I noticed about your code:
You code does not handle multiple Cookie headers on the response. Mine seems to handle that better.
Are you sure that all you need is JSESSION? Maybe there are other cookies you are missing?
Have you debugged your code to make sure that your JSESSION cookie gets set appropriately? I added some trim() calls in my cookie processing code to make sure some spaces didn't slip in there.
I can't see the real value of your secondParameters. I have no idea if they are valid. Have you debugged your code to verify the secondParamters value looks good. You can see in my code what I'm posting to the server. Btw, I'd use a StringBuilder instead of + to build them.
Hope this helps.
Sorry, I'm quite new to Java.
I've stumbled across HttpGet and HttpPost which seem to be perfect for my needs, but a little long winded. I have written a rather bad wrapper class, but does anyone know of where to get a better one?
Ideally, I'd be able to do
String response = fetchContent("http://url/", postdata);
where postdata is optional.
Thanks!
HttpClient sounds like what you want. You certainly can't do stuff like the above in one line, but it's a fully-fledged HTTP library that wraps up Get/Post requests (and the rest).
I would consider using the HttpClient library. From their documentation, you can generate a POST like this:
PostMethod post = new PostMethod("http://jakarata.apache.org/");
NameValuePair[] data = {
new NameValuePair("user", "joe"),
new NameValuePair("password", "bloggs")
};
post.setRequestBody(data);
// execute method and handle any error responses.
...
InputStream in = post.getResponseBodyAsStream();
// handle response.
There are a number of advanced options for configuring the client should you eventually required those.