Django-Piston and Python Client Vs Java Client - java

I've built a web service using Django-Piston that allows for POST and GET requests. As part of testing I wrote a quick Python script. Using the script I can successfully do both types of requests; however, when a client written in Java attempts to do a POST I get an error: "POST /api/service/ HTTP/1.1" 400 225 "-" "Apache-HttpClient/4.1 (java 1.5)"
My understanding is that http request message that is generated by any language has to be the same. In other words, if I test my web service using a python client and it works then it should work for all other languages that have a http library.
Here is the python code for the POST:
import urllib, urllib2
data = urllib.urlencode({'url': 'www.uvic.ca', 'name': 'uvic'})
url = 'http://xxx/api/service/'
req = urllib2.Request(url, data)
print urllib2.urlopen(req).read()
and here is the Java code:
HttpPost httpost = new HttpPost("http://xxx/api/service/");
List <NameValuePair> nvps = new ArrayList <NameValuePair>();
nvps.add(new BasicNameValuePair("name", "some_name"));
nvps.add(new BasicNameValuePair("url", "www.somename.com"));
httpost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
response = httpclient.execute(httpost);
entity = response.getEntity();
System.out.println(entity.getContentType());
System.out.println(EntityUtils.getContentCharSet(entity));
System.out.println(EntityUtils.toString(entity));
I'm starting to think that this is an apache configuration problem. I put in some debugging statements at the start of my method for POST and I'm not hitting them at all. This means that something is wrong with the urls.py file (which I doubt because it works in python) or something is weird with apache.
Please help. Thanks in advance.

A little search would help you a lot. This was the first Google result.
http://weblog.mattdorn.com/content/restful-web-apps-with-django-piston-and-ext-js/
The reason for the 400 errors is that
ExtJS is appending a charset onto the
Content-Type field, which causes
piston to not interpret the
Content-Type correcly. There is an
open issue for it at
http://bitbucket.org/jespern/django-piston/issue/121/content-type-is-not-being-split-against.
I was able to get the example working
after I applied the patch and did an
easy_install.
This is the second Google response.
https://bitbucket.org/jespern/django-piston/issue/99/bad-request-and-content-type-with-fix

Related

Migrate OOB in HTTP POST request to googleapis

We are making use of this end point - https://www.googleapis.com/oauth2/v4/token
to get the access token.
We make use of apace HTTP classes to make a POST request to this end point in this way -
HttpPost httpPost = new HttpPost(GET_ACCESS_TOKEN_API);
StringBuilder blr = new StringBuilder().append(CLIENT_ID).append("=")
.append((String) accountCredentials.get(CLIENT_ID)).append("&")
.append(CLIENT_SECRET).append("=")
.append((String) accountCredentials.get(CLIENT_SECRET))
.append("&").append(REFRESH_TOKEN).append("=")
.append((String) accountCredentials.get(REFRESH_TOKEN))
.append("&grant_type=refresh_token")
.append("&redirect_uri=urn:ietf:wg:oauth:2.0:oob");
// The message we are going to post
StringEntity requestBody = new StringEntity(blr.toString());
// the default content-type sent to the server is
// application/x-www-form-urlencoded.
requestBody.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(requestBody);
// Make the request
HttpResponse response = HttpUtils.getHttpClient().execute(httpPost);
There has been a recent intimation from google to migrate from out-of-band as they have plans to deprecate this.
We make use of it this way as you can see in the code above -append("&redirect_uri=urn:ietf:wg:oauth:2.0:oob");
GET_ACCESS_TOKEN_API is https://www.googleapis.com/oauth2/v4/token.
I saw some posts mentioning that we have to replace this redirect_uri to localhost.
Can someone explain exactly how this works and what change needs to be done to migrate this successfully ? I tried searching through the documentation to see if there any sample examples but couldn't find anything that matches our use case.
I am referring to this site -
https://developers.google.com/api-client-library/java/google-oauth-java-client/support
I tried to browse through samples, guides, but it mostly talks about different API's. I didn't find the github links that much useful.
Any help would be much appreciated.

Java - RestTemplate 405 Method Not Allowed Although Postman Call Works

I am experiencing a weird issue when working with RestTemplate. I'm using a certain REST API and there I want to update something using PUT.
Thus, in e.g. Postman I am sending this request:
PUT http://fake/foobar/c/123 with a certain body
This update via Postman is successful. If I now execute the same call in Java via a RestTemplate, I am getting a 405 Method Not Allowed:
HttpHeaders headers = createHeader();
HttpEntity<Offer> httpEntity = new HttpEntity<>(bodyEntity, headers);
String url = "http://fake/foobar/c/123"; //Created dynamically, but here pasted for sake of simplicity
RestTemplate restTemplate = new RestTemplate(...);
ResponseEntity<OfferResponse> response = restTemplate.exchange(url, HttpMethod.PUT, httpEntity, OfferResponse.class);
...
I compared the URL again and again. If I copy the URL logged in the console and copy it to Postman, I can do the update successfully. I also compared the headers and everything. Everything is equal to how it is done via Postman.
Is there any potential other reason for such a behavior (another reason than I am too stupid comparing the headers etc. and missing something)? Other PUT, POST calls etc. against this API are working fine, otherwise I would have assumed that there is a general problem with my usage of RestTemplate
Code 405 Method Not Allowed means the HTTP verb (GET, POST, PUT, etc.) you use against this end-point is known but not accepted by the API.
If you can't post the details of your API as #Dinesh Singh Shekhawat suggested, I will first try to use Postman Code feature and get an automatically generated code for Java (OkHTTP or UniRest) of the request. You can find this option on the right part below the Send button. Copy this code and try to perform the request.
Then compare this request with yours.
You can always use HttpPut instead of RestTemplate if it's not a requirement:
HttpClient client = HttpClientBuilder.create().build();
String url = "http://fake/foobar/c/123";
HttpHeaders headers = createHeader();
HttpEntity<Offer> httpEntity = new HttpEntity<>(bodyEntity, headers);
HttpPut httpPut = new HttpPut(url);
httpPut.setEntity(httpEntity);
HttpResponse response = client.execute(httpPut);
I was facing the same problem. Later I printed the request and URL in the logs.
I found that I was using a wrong endpoint.
Can you please try to print the URL and the request in the logs and check if those are expected and correct?
Just in case it helps someone else: I was encountering the same issue and for me it was just the issue of a trailing slash / on the URL. In insomnia (similar to postman) I had a trailing slash, in code I didn't. When I added the slash to my code everything worked.
failure: http://localhost:8080/api/files
success: http://localhost:8080/api/files/
Of course it could also be the other way around, so just double check the actual api definition.

Apache HttpClient. How to properly produce multipart requests with Encoding

Similar to the already existing question Apache HttpClient making multipart form post
want to produce a http request, holding a file and a key=val pair.
Currently the code looks like:
HttpPost post = new HttpPost("http://localhost/mainform.cgi/auto_config.htm");
HttpEntity ent = MultipartEntityBuilder.create()
.addTextBody("TYPE", "6",ContentType.TEXT_BINARY)
.addBinaryBody("upname", new File("factory.cfg"),ContentType.APPLICATION_OCTET_STREAM,"factory.cfg")
.build();
This is simply applied to HttpPost object as entity and passed to the client.
Which is sent to a linux-type device (blackbox) with a lighthttp service running. The problem is that when I send this request I do not see a response from the device(physical, and the HttpEntity always returns a default 200 OK).
Through Wireshark I've noticed two differences, on which i would really appreciate to get some help:
1. The multipart elements have an additional header(comparing to the original request) - Content-transfer-encoding, which i assume may be the reason of the fail.
2. Content length differs drastically.
So the first question would be - how to deal with the Encoding?
Found the point, on which it was failing. Needed this addition:
.addTextBody("TYPE", "6",ContentType.WILDCARD)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE).setCharset(Charset.forName("UTF-8"))

How to Request an External JSON URL From Within Java Servlet or Class When the JSON URL sits behind NTLM Authentication On Another Server/Domain

Accessing the following JSON URL from within the web browser is simple on a Windows machine as this pops up an authentication box asking for the username and password which when entered displays the JSON data correctly.
www.json-behind-ntlm-authentication.com/view-data
I am now trying to move this into a Java Servlet.
I have tested the HttpClient library, http://hc.apache.org, and every example I have tried from their documentation, doesn't work. Most of the code I've tried doesn't even compile correctly.
I have also tested Jsoup, https://jsoup.org/, as that is a very good library for web scraping, but this doesn't seem to support accessing pages behind NTLM authentication.
I have also tested the code found here, https://blogs.msdn.microsoft.com/freddyk/2010/01/19/connecting-to-nav-web-services-from-java/, which is the only code sample I can find related to accessing a JSON URL that sits behind NTLM authentication. This is actually what I'm looking to achieve, a Java web application accessing Microsoft Nav data through their web services - and even this official example doesn't compile.
Any pointers / options? There must be a Java library somewhere that has this problem solved? The access is currently over HTTP, but ultimately is going to be over SSL for security reasons, so any solution must also support SSL handshakes.
I would really like not to build a separate C# application using LINQ, https://blogs.msdn.microsoft.com/freddyk/2009/04/20/using-linq-with-nav-web-services/, which I would hope works, but I'm not hopeful that the C# example would work in this scenario based on the Java examples not compiling.
UPDATE
After an awful lot of searching, I've found the following code below which seems to be close to working, but not quite - See the comments in the code where this is breaking. Thanks for the pointers in the comments already.
DefaultHttpClient httpclient = new DefaultHttpClient();
List<String> authpref = new ArrayList<String>();
authpref.add(AuthPolicy.NTLM);
httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref); //ERROR - This causes an error: java.lang.VerifyError: Cannot inherit from final class
NTCredentials creds = new NTCredentials(username, password, "", domain);
httpclient.getCredentialsProvider().setCredentials(AuthScope.ANY, creds);
HttpHost target = new HttpHost(baseURL);
// Make sure the same context is used to execute logically related requests
HttpContext localContext = new BasicHttpContext();
// Execute a cheap method first. This will trigger NTLM authentication
HttpGet httpget = new HttpGet(baseURL);
HttpResponse response1 = httpclient.execute(target, httpget, localContext); //ERROR - This line is throwing an error: java.lang.VerifyError: Cannot inherit from final class
HttpEntity entity = response1.getEntity();
System.out.println(EntityUtils.toString(entity));
I'm still unsure how to actually solve this problem. Any additional pointers?
org.apache.http.auth has NTCredentials which you can use in a HttpComponentsMessageSender in a spring boot #Configuration
HttpComponentsMessageSender httpComponentsMessageSender = new HttpComponentsMessageSender();
NTCredentials credentials = new NTCredentials("username", "password", null, "domain");

Java http post: Difference in reading bytes through curl and in java

I am stuck in a strange issue, I am posting some image data to a server, now I created the requested using curl and then traced back it.
Next was to create similar request in java.
The code posts raw binary image data to server, but when I compare the binary data in java to that posted by curl, there is a minute difference due to which I am getting 400 response code from server.
The difference I think is in few dots.
Below is the request generate by curl (linux).
Generate by curl
Now here is the request generate by Java, when I read bytes.
Click here
Java code looks something like this:
PrintWriter out = new PrintWriter(os);
out.println("POST /1izb0rx1 HTTP/1.1");
out.println("User-Agent: curl/7.35.0");
out.println("Host: requestb.in");
out.println("Accept: */*");
out.println("Content-Disposition:inline; filename=test.png");
out.println("Authorization: Basic YW5kcm9pZDpUZXN0dGVzdDExISE=");
out.println("Content-Length: "+"24143");
out.println("Content-Type: application/x-www-form-urlencoded");
out.println();
out.println("."+imgBytes);
Any idea what can be causing this issue ?
Thanks
So,
I got it working, the problem was that certain classes on Android are broken and not behaving as the way they behave on core Java.
The same code that was working on Java, wasn't working here, reason being, a change in header occurring here (On Android).
This issue is very well mentioned here also:
https://github.com/WP-API/WP-API/issues/1862
Thus I was facing a similar issue, and adding external updated jars were conflicting with the ones on Android.
Finally I used a small HTTP Request library: https://github.com/kevinsawicki/http-request
The code is below:
HttpRequest request = HttpRequest.post(url);
request.authorization("Basic "+ah);
request.part("file", fName+".png", "image/png", new File(file));
request.part("title", "test");
if(request.code()==201) {
StringWriter sw = new StringWriter();
request.receive(sw);
onMedia(Media.parse(new JsonParser().parse(sw.toString()).getAsJsonObject()));
}
Thanks
Do not use PrintWriter to send raw bytes.

Categories