How can I set content type of HTTP Put as xxxx+xml?
I was referring to solution in this link Android, sending XML via HTTP POST (SOAP). Its fine when we set content type like this, i mean the xml is came along with the request:
httppost.setHeader("Content-Type","application/soap+xml;charset=UTF-8");
but when i change type soap to something custom, the xml disappear on the request (i saw on the wireshark), like this:
httppost.setHeader("Content-Type","application/vnd.oma-pcc+xml;charset=UTF-8");
then, i tried put the xml only, so the request is ok again:
httppost.setHeader("Content-Type","application/xml;charset=UTF-8");
I want to know what exactly the rules for the content-type than come together with the xml type so that the xml still there.
Thanks.
Assuming you're using HTTPClient of 4.1.3 or greater -
When constructing you're entity, you have the option to specify the content being used for the POST or PUT operation for certain entities.
There is a ContentType object which should be used to specify this.
Using the factory method .create() you can specify the mimetype with a charset - the ContentType will be used by the framework to properly emit the header in question.
Example API call:
ContentType.create("application/vnd.oma-pcc+xml", CharSet.forName("UTF-8"));
NOTE Editing for HttpClient 4.1.2
In the case of 4.1.2, when you create your entity for the post or put operation, set the content type on the entity not the execution (HttpPost or HttpPut) using setContentType(String). This is deprecated in 4.1.3 and beyond.
Related
I need to configure a parser which can add few default fields(such as default labels) in the request body of underlying BQ HTTP request whenever any query is run via this bqserv instance (like mentioned in the code snippet below). How to build bqserv?
bqserv.query(QueryJobConfiguration.newBuilder(query).build)
I found BigQueryOptions.newBuilder().setTransportOptions() to set transport options, but I am unable to figure out exactly how to configure/(or set a parser for) HTTP request body ? I came across com.google.cloud.spark.bigquery.repackaged.com.google.api.client.util.ObjectParser as well, but again not sure how to use it and create bqserv (class com.google.cloud.spark.bigquery.repackaged.com.google.cloud.bigquery.BigQueryImpl) object.
My web service, which is a java servlet, accepts a put request with url params to take a specific action. The code below gets what I want done, but I would love to know if there is a better way to make a put request without adding a multipart body.
Do all put requests in Java Servlets expect a multipart body?
Do all put requests made using okhttp3 expect a multipart body?
Am I misunderstanding something else?
body = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("", "") // I would love to eliminate this.
.build();
request = new Request.Builder()
.url(url + "?my_param=" + URLEncoder.encode(myParam, "utf-8"))
.put(body)
.build();
response = client.newCall(request).execute();
From a pragmatic point of view, I'd say that you're looking at an implementation restriction of Servlets and/or OkHttp and it can probably be made to work using different libraries.
However,
from a standards view, I think your approach is incorrect and you should use a POST instead of a PUT. This requires reading both RFC-2616 (HTTP/1.1), section 9.6 on the POST request, and RFC-1630 (URL's in WWW), the section on query strings.
From the HTTP spec, section 9.6:
The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource.
From the URL's spec, page 6:
QUERY STRINGS
The question mark ("?", ASCII 3F hex) is used to delimit the boundary between the URI of a queryable object, and a set of words used to express a query on that object. When this form is used, the combined URI stands for the object which results from the query being applied to the original object.
These two combine to imply that you cannot use a PUT request in the way that you're trying to.
so currently I'm retrieving the data from a url using the following code
Document doc = Jsoup.connect(url).get();
Before I fetch the data I've decided I want to get the content type, so I do that using the following.
Connection.Response res = Jsoup.connect(url).timeout(10*1000).execute();
String contentType = res.contentType();
Now I'm wondering, is this making 2 separate connections? Is this not efficient? Is there a way for me to get the content type and the document data in 1 single connection?
Thanks
Yes Jsoup.connect(url).get() and Jsoup.connect(url).timeout(10*1000).execute(); are two separate connections. Maybe you are looking for something like
Response resp = Jsoup.connect(url).timeout(10*1000).execute();
String contentType = res.contentType();
and later parse body of response as a Document
Document doc = resp.parse();
Anyway Jsoup by default parses only text/*, application/xml, or application/xhtml+xml and if content type is other, like application/pdf it will throw UnsupportedMimeTypeException so you shouldn't be worried about it.
Without looking at the Jsoup internals we can't know. Typically when you want to obtain just the headers of a file (the content type in your case) without downloading the actual file content, you use the HTTP GET method instead of the GET method to the same url. Perhaps the Jsoup API allows you to set the method, that code doesn't seem like it's doing it so I'd wager it's actually getting the entire file.
The HTTP spec allows clients to reuse the connection later, they are called HTTP persistent connections, and it avoids having to create a connection for each call to the same server. However it's up to the client, Jsoup in this case since you aren't handling the connections in your code, to make sure it's not closing the connections after each request.
I believe that the overhead of creating two connections is offset by not downloading the entire file if you're code decides that it shouldn't download the file if it's not of the content type that you want.
My main question is how can I pass JSON as well as File to post request to REST API? What needs in Spring framework to work as client and wait for response by passing post with JSON and File?
Options:
Do I need to use FileRepresentation with ClientResource? But how can I pass file as well as JSON?
By using RestTemplate for passing both JSON as well as File? How it can be used for posting JSON as well as File?
Any other option is available?
Sounds like an awful resource you're trying to expose. My suggestion is to separate them into 2 different requests. Maybe the JSON has the URI for the file to then be requested…
From a REST(ish) perspective, it sounds like the resource you are passing is a multipart/mixed content-type. One subtype will be application/json, and one will be whatever type the file is. Either or both could be base64 encoded.
You may need to write specific providers to serialize/deserialize this data. Depending on the particular REST framework, this article may help.
An alternative is to create a single class that encapsulates both the json and the file data. Then, write a provider specific to that class. You could optionally create a new content-type for it, such as "application/x-combo-file-json".
You basically have three choices:
Base64 encode the file, at the expense of increasing the data size
by around 33%.
Send the file first in a multipart/form-data POST,
and return an ID to the client. The client then sends the metadata
with the ID, and the server re-associates the file and the metadata.
Send the metadata first, and return an ID to the client. The client
then sends the file with the ID, and the server re-associates the
file and the metadata.
I'm using restlet 2.0.11 to provide data for a Dojo-based web application via a REST-Web-Interface.
According to the documentation of dojo, pagination is realized using the "content-range" header of HTTP, thus dojo expects a header like:
Content-Range: items 0-19/100
(Source: http://dojotoolkit.org/reference-guide/1.7/dojox/data/JsonRestStore.html)
Which means that the REST-Api provides the first 20 of 100 total items.
Setting the Content-Range header manually like this
getResponse().getAttributes().get("org.restlet.http.headers").add(new Parameter("Content-Range", "FooBar")
Results in the following error:
WARNING: Addition of the standard header "Content-Range" is not allowed. Please use the equivalent property in the Restlet API.
According to restlet's documentation the property is "message.entity.range" (Source: http://wiki.restlet.org/docs_2.0/130-restlet.html)
The direct modification of this hash-map was also without success:
getResponse().getAttributes().put("message.entity.range", "FooBat");
Another way which seemed to be promising is using the "Representation"-object of restlet, since it has a setRange() method, but during request time, the object reference is null:
getResponse().getEntity()
So my question is: How to set a Content-Range header to a Restlet response?
You have to use the equivalent Java properties in the Representation class, so this is getResponse().getEntity().setRange(myRange).