Do I need to add Content-Type header if I already set the StringEntity's content type? - apache-httpclient-4.x

I need to do a POST request against a server with a UTF-8 JSON in the body:
public HttpRequest createRequest() {
HttpPost req = new HttpPost(API_URL);
StringEntity stringEntity = new StringEntity(notification.toString(), Charset.forName("UTF-8"));
stringEntity.setContentType(ContentType.APPLICATION_JSON.toString());
req.setEntity(stringEntity);
return req;
}
Are stringEntity's content type and charset added automatically to the request?
Or do I have to add the header to req?
req.addHeader("Content-Type", "application/json; charset=UTF-8");

No, you do not. Content metadata headers are generated automatically by RequestContent protocol interceptor.

Related

How do I get the body of the POST request with WCF?

I want to get the body of the POST request in json format with WCF, below is my code:
Service
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "/GetBody", BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
void GetBody(Stream stream);
Client(uses restsharp)
var client = new RestClient("http://127.0.0.1");
var request = new RestRequest("/GetBody", Method.POST);
request.AddParameter("application/json", "{\"PortalType\":\"Merchant\"}", ParameterType.RequestBody);
var response = client.Execute(restRequest);
I get the following error: "StatusCode: BadRequest, Content-Type: text/html, Content-Length: 2897)"
I tried various methods but never succeeded, can only ask for help!
If the client code is changed to the following, then the body can be successfully obtained.
var client = new RestClient("http://127.0.0.1");
var request = new RestRequest("/GetBody", Method.POST);
//request.AddParameter("application/json", "{\"PortalType\":\"Merchant\"}", ParameterType.RequestBody);
requst.AddParameter("PortalType", "Merchant");
var response = client.Execute(restRequest);
This is because the request parameter of your GetBody is of type Stream, and you set the Content-Type to application/json when sending the request to the WCF service, so the WCF service will report a bad request error.
When we want to send a Stream data, the Content-Type should be application/octet-stream, If you do not set the Content-Type, the Content-Type defaults to application/octet-stream when transmitting Stream type data.
I have found the right solution. You need to set the ContentTypeMapper of the web service to force it to use raw to parse the request.

Spring MVC to send responsebody object to ajax post gives 406 error

There are similar links but I haven't found any solution to work for me, so I was wondering if someone could give me a working example for my scenario. I am doing an ajax get to retrieve data from the server side, so I can create charts dynamically on the client side. Do I need to include MappingJacksonHttpMessageConverter? If that's the answer can someone provide an example i can follow for that?
Java:
#RequestMapping(value="/getReportData.html", method=RequestMethod.GET, produces="application/json")
public #ResponseBody Reports getReport1Data(HttpServletRequest request)
{
System.out.println("Report 1 Page GET Method");
ModelAndView mv = new ModelAndView("report1");
if((Reports)request.getSession().getAttribute(USER_SESSION_REPORTS) != null){
reports = (Reports)request.getSession().getAttribute(USER_SESSION_REPORTS);
System.out.println("--------> Report 1 Page with session data");
return reports;
}
else{
System.out.println("--------> Report 1 Page with NO session data");
}
mv.addObject("report1", reports.getReport1());
return null;
}
Javascript:
function getData(){
$.ajax({
url: "getReportData.html",
type: "GET",
contentType: "application/json",
dataType: JSON,
success: function(report1){
console.log("success: " + report1.utilRatio.decRatio);
},
error: function(report1){
console.log("error: " + report1.utilRatio.decRatio);
}
});
}
Response Headers:
Content-Language: "en",
Content-Length: "1110"
Content-Type: "text/html;charset=utf-8"
Server: "Apache-Coyote/1.1"
Request Headers:
Accept: "/"
Accept-Language: "en-US,en;q=0.5"
Accept-Encoding: "gzip,deflate"
Content-Type: "application/json"
X-Requested-With: "XMLHttpRequest"
It looks like your request headers are wrong. You can remove the contentType setting since you are not sending data to the server and change dataType to the string value "json" instead of the variable JSON.
Also, your response headers are wrong. Just make sure you are always returning a Reports object. And you probably want to remove the html extension from that endpoint since you're just returning an object.
spring uses #ResponseBody annotaion for returning data as json .it will implicitly call the MappingJacksonHttpMessageConverter .so you need to use it.
#RequestMapping(value = "/getjson", method = RequestMethod.POST, produces = "application/json")
#Transactional
public void getJson(HttpServletRequest request, HttpServletResponse response, #RequestParam("type") String type)
throws DatatypeConfigurationException, IOException, JSONException {
JSONObject json = new JSONObject();
Map<String, String[]> parameterMap = request.getParameterMap();
List<Chart> chart=myService.getChart();
if (Chart.size()>0) {
json.put("status", "SUCCESS");
JSONArray array = new JSONArray();
for (Chart chartData: chart) {
JSONObject object = new JSONObject();
object.put("id", chartData.getRaasiId());
object.put("name", chartData.getName());
array.put(object);
}
json.put("options", array);
}
}
}
response.setContentType("application/json");
System.out.println("response======" + json.toString());
PrintWriter out = response.getWriter();
out.write(json.toString());
}
============
on the html
jQuery
.ajax({
url : controllerUrl,
dataType : 'text',
processData : false,
contentType : false,
type : 'GET',
success : function(response) {
success : function(response) {
marker = JSON.stringify(response);
json = jQuery.parseJSON(marker);
json = JSON.parse(json);
alert(json.status);
}
});
for reference:
https://rwehner.wordpress.com/2010/06/09/2-ways-to-create-json-response-for-ajax-request-in-spring3/

sending JSON to server windows phone 8

i'm trying to send JSON string to server using Web Client Class but No result is returned,i've tried Rest Client plugin to make sure that server is returning something, here's my postRequest method `
public static void PostRequest(WebClient webclient,string data,string
url,string header,string method)
{
Uri uri = new Uri(url, UriKind.Absolute);
webclient.Headers[HttpRequestHeader.ContentType] = header;
webclient.UploadStringAsync(uri,method,data);
}
and here is where i invoke this method
string newUserJson="{"User_Name":"yosyos","First_Name":"gfhgas","Last_Name":"jagfshg"}";
wc = new WebClient();
wc.UploadStringCompleted += new UploadStringCompletedEventHandler(wb_UploadStringCompleted);
string url = "http://670b9ada.ngrok.com/laravelProjects/TestVisWall/public/users";
helper.PostRequest( wc, newUserJson, url, "application/json", "POST");
Do not use WebClient, it's discouraged from Microsoft.
Try RestSharp library, in my opinion is a very good one. Add recerense to Restsharp, Nuget method is faster: https://www.nuget.org/packages/RestSharp
RestClient client = new RestClient("baseurl");
var request = new RestRequest("/path/script.php", Method.POST);
request.AddParameter("application/json; charset=utf-8", "json string", ParameterType.RequestBody);
request.RequestFormat = DataFormat.Json;
client.ExecuteAsync(request, response =>
{
if (response.StatusCode == HttpStatusCode.OK)
{
//OK
}
});
}

Spring MVC Multipart Request with JSON

I want to post a file with some JSON data using Spring MVC. So I've developed a rest service as
#RequestMapping(value = "/servicegenerator/wsdl", method = RequestMethod.POST,consumes = { "multipart/mixed", "multipart/form-data" })
#ResponseBody
public String generateWSDLService(#RequestPart("meta-data") WSDLInfo wsdlInfo,#RequestPart("file") MultipartFile file) throws WSDLException, IOException,
JAXBException, ParserConfigurationException, SAXException, TransformerException {
return handleWSDL(wsdlInfo,file);
}
When I send a request from the rest client with
content-Type = multipart/form-data or multipart/mixed, I get the next exception:
org.springframework.web.multipart.support.MissingServletRequestPartException
Can anyone help me in solving this issue?
Can I use #RequestPart to send both Multipart and JSON to a server?
This is how I implemented Spring MVC Multipart Request with JSON Data.
Multipart Request with JSON Data (also called Mixed Multipart):
Based on RESTful service in Spring 4.0.2 Release, HTTP request with the first part as XML or JSON formatted data and the second part as a file can be achieved with #RequestPart. Below is the sample implementation.
Java Snippet:
Rest service in Controller will have mixed #RequestPart and MultipartFile to serve such Multipart + JSON request.
#RequestMapping(value = "/executesampleservice", method = RequestMethod.POST,
consumes = {"multipart/form-data"})
#ResponseBody
public boolean executeSampleService(
#RequestPart("properties") #Valid ConnectionProperties properties,
#RequestPart("file") #Valid #NotNull #NotBlank MultipartFile file) {
return projectService.executeSampleService(properties, file);
}
Front End (JavaScript) Snippet:
Create a FormData object.
Append the file to the FormData object using one of the below steps.
If the file has been uploaded using an input element of type "file", then append it to the FormData object.
formData.append("file", document.forms[formName].file.files[0]);
Directly append the file to the FormData object.
formData.append("file", myFile, "myfile.txt"); OR formData.append("file", myBob, "myfile.txt");
Create a blob with the stringified JSON data and append it to the FormData object. This causes the Content-type of the second part in the multipart request to be "application/json" instead of the file type.
Send the request to the server.
Request Details:
Content-Type: undefined. This causes the browser to set the Content-Type to multipart/form-data and fill the boundary correctly. Manually setting Content-Type to multipart/form-data will fail to fill in the boundary parameter of the request.
Javascript Code:
formData = new FormData();
formData.append("file", document.forms[formName].file.files[0]);
formData.append('properties', new Blob([JSON.stringify({
"name": "root",
"password": "root"
})], {
type: "application/json"
}));
Request Details:
method: "POST",
headers: {
"Content-Type": undefined
},
data: formData
Request Payload:
Accept:application/json, text/plain, */*
Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryEBoJzS3HQ4PgE1QB
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="file"; filename="myfile.txt"
Content-Type: application/txt
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN
Content-Disposition: form-data; name="properties"; filename="blob"
Content-Type: application/json
------WebKitFormBoundaryvijcWI2ZrZQ8xEBN--
This must work!
client (angular):
$scope.saveForm = function () {
var formData = new FormData();
var file = $scope.myFile;
var json = $scope.myJson;
formData.append("file", file);
formData.append("ad",JSON.stringify(json));//important: convert to JSON!
var req = {
url: '/upload',
method: 'POST',
headers: {'Content-Type': undefined},
data: formData,
transformRequest: function (data, headersGetterFunction) {
return data;
}
};
Backend-Spring Boot:
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public #ResponseBody
Advertisement storeAd(#RequestPart("ad") String adString, #RequestPart("file") MultipartFile file) throws IOException {
Advertisement jsonAd = new ObjectMapper().readValue(adString, Advertisement.class);
//do whatever you want with your file and jsonAd
You can also use the next way a list List<MultipartFile> and #RequestPart("myObj") as parameters in your method inside a #RestController
#PostMapping()
#ResponseStatus(HttpStatus.CREATED)
public String create(#RequestPart("file") List<MultipartFile> files, #RequestPart("myObj") MyJsonDTOClass myObj) throws GeneralSecurityException, IOException {
// your code
}
and in the axios side with a bit of react:
const jsonStr = JSON.stringify(myJsonObj);
const blob = new Blob([jsonStr], {
type: 'application/json'
});
let formData = new FormData();
formData.append("myObj",blob );
formData.append("file", this.state.fileForm); // check your control
let url = `your url`
let method = `post`
let headers =
{
'Accept': 'application/json',
'Content-Type': 'application/json'
};
}
axios({
method,
url,
data: formData,
headers
}).then(res => {
console.log(res);
console.log(res.data);
});
We've seen in our projects that a post request with JSON and files is creating a lot of confusion between the frontend and backend developers, leading to unnecessary wastage of time.
Here's a better approach: convert file bytes array to Base64 string and send it in the JSON.
public Class UserDTO {
private String firstName;
private String lastName;
private FileDTO profilePic;
}
public class FileDTO {
private String base64;
// just base64 string is enough. If you want, send additional details
private String name;
private String type;
private String lastModified;
}
#PostMapping("/user")
public String saveUser(#RequestBody UserDTO user) {
byte[] fileBytes = Base64Utils.decodeFromString(user.getProfilePic().getBase64());
....
}
JS code to convert file to base64 string:
var reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = function () {
const userDTO = {
firstName: "John",
lastName: "Wick",
profilePic: {
base64: reader.result,
name: file.name,
lastModified: file.lastModified,
type: file.type
}
}
// post userDTO
};
reader.onerror = function (error) {
console.log('Error: ', error);
};
As documentation says:
Raised when the part of a "multipart/form-data" request identified by
its name cannot be found.
This may be because the request is not a multipart/form-data either
because the part is not present in the request, or because the web
application is not configured correctly for processing multipart
requests -- e.g. no MultipartResolver.
For Angular2+ users. Try to send JSON payload in a mixed part request as below.
formData.append("jsonPayload", new Blob([JSON.stringify(json)], {
type: "application/json"
}));
Given below complete function.
submit() {
const formData = new FormData();
formData.append('file', this.myForm.get('fileSource').value);
var json = {
"key":"value"
};
formData.append("jsonPayload", new Blob([JSON.stringify(json)], {
type: "application/json"
}));
this.http.post('http://localhost:8080/api/mixed-part-endpoint', formData)
.subscribe(res => {
console.log(res);
alert('Uploaded Successfully.');
})
}

Getting FW/1 2.2 to return application/json

FW/1 has a function buried inside of it
private string function renderDataWithContentType() {
var out = '';
var contentType = '';
var type = request._fw1.renderData.type;
var data = request._fw1.renderData.data;
var statusCode = request._fw1.renderData.statusCode;
switch ( type ) {
case 'json':
contentType = 'application/json; charset=utf-8';
out = serializeJSON( data );
break;
It looks like it has a build in mechanism to return application/json, text/xml, and text/plain.
I can't find any documentation on how to trigger this.
Note: this is not a duplicate of: How do I return JSON from an action in FW/1?
You could read the documentation:
From the documentation
...
As of 2.2, you can return data directly, bypassing views and layouts, using the new renderData() function.
variables.fw.renderData( contentType, resultData );
Calling this function does not exit from your controller, but tells FW/1 that instead of looking for a view to render, the resultData value should be converted to the specified contentType and that should be the result of the complete HTTP request.
contentType may be “json”, “xml”, or “text”. The Content-Type HTTP header is automatically set to:
application/json; charset=utf-8
text/xml; charset=utf-8
text/plain; charset=utf-8
...