Setting Content type with Default Request Headers - dotnet-httpclient

When using HttpClient, I have read examples (such as this example) that uses DefaultRequestHeaders to set the content type (such as "application/json") of a Post request.
I tried to do something like this, but it failed. The API I am sending requests complained that it was sent an "unsupported type" (which it says when the content type is not set to json).
After that I added one line and I solved the issue (you can see the line in the code below commented).
My question is why is this line necessary? And if I include this line (that is setting the content type of the content) doesn't that make the "default request header" setting unnecessary. What is this "default request header" doing if anything?
(I actually tried and commented the lines related to DefaultRequestHeaders and it worked without problem. So what is DefaultRequestHeaders good for?)
My code is :
// Get the bytes for the request, should be pre-escaped
byte[] bytes = Encoding.UTF8.GetBytes(jsonEmployeeData);
client.BaseAddress = new Uri("the address here");
// client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("customHeader", "blahblahblah");
ByteArrayContent byteContent = new ByteArrayContent(bytes); //Make a new instance of HttpContent (an abstract class that can't be instantiated)
//THIS is the solution
//byteContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json"); //If I UNCOMMENT THIS, IT WORKS!!
try
{
HttpResponseMessage response = await client.PostAsync("staff", byteContent);
Console.WriteLine(response.ToString());
}
catch (Exception ex)
{
Console.WriteLine("Something happened, oopps!" + ex.Message);
}
Console.WriteLine("Press any key");
Console.ReadLine();
client is a HttpClient by the way.

The API you called needs the request content is application/json format, so you have to specify this format in your content. That's why that line of code is the one you need:
byteContent.Headers.ContentType = new MediaTypeWithQualityHeaderValue("application/json");
About the line:
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"))
This is request Accept header, it means the content type of response which you expect the server return to you. (You can expect server returns another content type like text/plain,...). Hope this helps!

Related

How to use custom ApacheHttpClient with Feign?

I've tried to add a custom HttpClient via configuration:
#Bean
public CloseableHttpClient httpClient() {
RequestConfig requestConfig = RequestConfig.custom()
.setConnectTimeout(15000)
.setConnectionRequestTimeout(15000)
.build();
Header header = new BasicHeader("Test", "Test");
Collection<Header> headers =Arrays.asList(header);
return HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setDefaultHeaders(headers)
.build();
}
but still, my custom added default header doesn't appear in the request.
My Feign client interface looks like below:
#FeignClient(name = "example",
url = "${client.example.api}",
decode404 = false,
configuration = FeignClientConfiguration.class)
public interface ExampleFeignProxy{
#PostMapping(path = "/create")
#Headers("Content-Type: application/json")
String Create(
#RequestBody ExampleDTO exampleDto,
#RequestHeader("access-token") String token);
}
but when I make request to the Create method, request fails, when I inspect inside configuration.errordecoder, it shows feign is adding an extra header Content-Length also to the request.
How can I remove default headers from all methods inside my feign client?
To make it clear - as shown above, only two headers should have been present on the request object
Content-Type
Access-Token
but Feign somehow adds Content-Length as well.
Is there a configuration somewhere I need to set?
Actually, it was a misunderstanding, above configuration was always working, I was not parsing the error properly. The error returned was actually from the api.
All I had to do was to properly specify the errordecoder.

maintaining sessions with RestAssured

How to set session attributes in restassured? In my application code we have something like this
String userId= request.getSession().getAttribute("userid")
How to set userId as session attribute here(in restassured test case)?
How to maintain the same session for all the requests(multiple subsequent requests)?
When i send multiple requests, it's considering every request as new and session is getting invalidated from server side, i want to maintain session between subsequent calls.
I tried setting jsessionid in the cookie and sent it in the second request, but when i debugged in the server side, it's not loading the session which was created, instead it's creating different session and because of this its doesn't show the attribute which i have set in the session when i first sent the request.
When i tried the same with direct HttpClient, it working, where as the same with RestAssured it's not working.
Code which was working with HttpClient is this
HttpClient httpClient = util.getHttpClient();
//1st request
HttpResponse response=httpClient.execute(postRequest);
from response i have extracted the jessionid and set this in the second request
HttpGet getRequest = new HttpGet(Client.endPointUrl);
getRequest.addHeader("content-type", "application/json");
getRequest.addHeader("accept", "application/json");
getRequest.addHeader("Origin", Client.endPointUrl);
getRequest.addHeader("Referer", Client.endPointUrl);
getRequest.addHeader("Auth-Token", authToken);
getRequest.addHeader("Set-Cookie", jsessionId);
//2nd request after setting the jessionid which i have extracted from the response
HttpResponse eventsResponse = httpClient.execute(getRequest);
Above code is working perfectly fine and i am getting expected response. One observation is i am using the same httpClient Object for invoking both the requests.
Where as i if i try the same using RestAssured, it's not working.
RestAssured.baseURI = "http://localhost:8080";
Response response=RestAssured.given().header("Content-Type","application/json").
header("Origin","http://localhost:8080").
header("Referer","http://localhost:8080").
body("{"+
"\"LoginFormUserInput\":{"+
"\"username\":\"test\","+
"\"password\":\"password\""+
"}"+
"}")
.when().post("/sample/services/rest/validateLogin").then().extract().response();
JsonPath js=Util.rawToJson(response);
String sessionId=js.get("sessionID");
System.out.println(sessionId);
for (Header header:response.getHeaders()) {
if ("Set-Cookie".equals(header.getName())) {
id= header.getValue().split(";")[0].trim();
String[] arr=jsessionId.split("=");
jsessionId=arr[0];
break;
}
}
response=RestAssured.given().header("Auth-Token",sessionId).header("Content-Type","application/json").
cookie("JSESSIONID",jsessionId).
header("Origin","http://localhost:8080").
header("Referer","http://localhost:8080").
body("{}").
when().
post("/sample/services/rest/getAllBooks").then().contentType("").extract().response();
I tried reusing the same httpclient for all the requests using the following, but it didn't work
RestAssured.config = RestAssured.config().httpClient( new HttpClientConfig().reuseHttpClientInstance());
You need to use Session filter in Rest Assured
https://github.com/rest-assured/rest-assured/wiki/Usage#session-support

How to send data from client to server using Rikulo stream

I'm trying to use Rikulo stream, and i have some trouble when i want to send data from client to server.
Suppose that i have a registration form and i want send a request to check if that username already exist in my database.
I have adopted MVC pattern, so i want that the controller received data and then, using a dao class, check if username exist or not.
In client side i have this lines of code
InputElement username = query('#username');
document.query("#submit").onClick.listen((e) {
HttpRequest request = new HttpRequest();
var url = "/check-existing-username";
request.open("POST", url, async:true);
request.setRequestHeader("Content-Type", "application/json");
request.send(stringify({"user": username.value}));
});
Is this the correct way to send data?
Here my server side code
void main(){
Controller controller = new Controller();
var _mapping = {
"/": controller.home,
"/home": controller.home,
"/check-existing-username" : controller.checkUsername
};
new StreamServer(uriMapping: _mapping).start();
And my controller method
void checkUsername(HttpConnect connect) {
//How to access data received from client?
}
The dao class is already defined, so i want only know how to access data.
I hope that someone can help me.
Since you're using POST, the JSON data will be in the HTTP request's body. You can retrieve it there. Rikulo Commons has a utility called readAsJson. You can utilize it as follows.
import "package:rikulo_commons/convert.dart";
Future checkUsername(HttpConnect connect) {
return readAsJson(connect.request).then((Map<String, String> data) {
String username = data["user"];
//...doa...
});
}
Notice that reading request's body is asynchronous, so you have to return a Future instance to indicate when it is done.

Blackberry-not getting soap response xml

I am trying to consume SOAP response xml by passing request xml in a string, using BlackBerry Java plugin for Eclipse. I have been struck on this for the past two days looking for a way to solve it.
I have attached the sample code below.
public String CheckXml()
{
final String requestXml="<SOAP:Envelope xmlns:SOAP=\"http://schemas.xmlsoap.org/soap/envelope/\"><header xmlns=\"http://schemas.cordys.com/General/1.0/\"></header><SOAP:Body><authenticateAgainstOID xmlns=\"http://schemas.cordys.com/OIDAuthentication\"><stringParam>HEMANTS_MUM013</stringParam><stringParam1>TATA2012</stringParam1></authenticateAgainstOID></SOAP:Body></SOAP:Envelope>";
final String HOST_ADDRESS = "http://xyz.com/cordys/com.eibus.web.soap.Gateway.wcp?organization=o=B2C,cn=cordys,cn=cbop,o=tatamotors.com&SAMLart=MDFn+8e5dRDaRMRIwMY7nI84eEccbx+lIiV0VhsOQ7u+SKG6n5+WNB58";
String result="";
try {
HttpConnection url=(HttpConnection)Connector.open(HOST_ADDRESS);
url.setRequestProperty("Content-Type", "text/xml");
url.setRequestMethod(HttpConnection.GET);
OutputStreamWriter writer=new OutputStreamWriter(url.openOutputStream());
writer.write(requestXml);
writer.flush();
writer.close();
StringBuffer buffer1=new StringBuffer();
InputStreamReader reader=new InputStreamReader(url.openInputStream());
StringBuffer buffer=new StringBuffer();
char[] cbuf=new char[2048];
int num;
while (-1 != (num = reader.read(cbuf))) {
buffer.append(cbuf, 0, num);
}
String result1 = buffer.toString();
} catch (Exception e) {
System.out.println(e);
}
return result;
}
I think the main issue that you aren't asking http. getResponseCode(). I think BB doesn't do any interaction until you call it.
I would also be careful with this code on the real devices. Search for correct opening connection on the BlackBerries.
I noticed that you are not including the SoapAction header in the request.
SOAP Web services usually have a fixed URL, and the differents methods are selected with the SoapAction header. You can check the header by opening the WSDL in a browser and inspecting the format for the method you want to invoke.
Once you know which action to select, set it as a regular http header:
url.setRequestProperty("SOAPAction", <your action here>);
Another source of problems in your code is that you are using the old HttpConnection class that requires appending a suffix to the URL depending on the transport type (MDS, BIS, Wi-Fi, etc). You don't need to use this legacy class unless you are targeting OS 4.5 and lower. So have a look at ConnectionFactory class, which is much easier to use. It is available since OS 5.0.

Getting 401 Unauthorized from Google API Resumable Update

I am trying to integrate upload of arbitrary files to Google Docs into an existing application. This used to work before using resumable upload became mandatory. I am using Java client libraries.
The application is doing the upload in 2 steps:
- get the resourceId of the file
- upload the data
To get the resourceId I am uploading a 0-size file (i.e. Content-Length=0). I am passing ?convert=false in the resumable URL (i.e. https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false).
I am passing "application/octet-stream" as content-type. This seems to work, though I do get different resourcesIds - "file:..." resourceIds for things like images, but "pdf:...." resourceIds for PDFs.
The second step constructs a URL based on the resourceId obtained previously and performs a search (getEntry). The URL is in the form of https://docs.google.com/feeds/default/private/full/file%3A.....
Once the entry is found the ResumableGDataFileUploader is used to update the content (0-byte file) with the actual data from the file being uploaded. This operation fails with 401 Unauthorized response when building ResumableGDataFileUploader instance.
I've tried with ?convert=false as well as ?new-revision=true and both of these at the same time. The result is the same.
The relevant piece of code:
MediaFileSource mediaFile = new MediaFileSource(
tempFile, "application/octet-stream");
final ResumableGDataFileUploader.Builder builder =
new ResumableGDataFileUploader.Builder(client, mediaFile, documentListEntry);
builder.executor(MoreExecutors.sameThreadExecutor());
builder.requestType(ResumableGDataFileUploader.RequestType.UPDATE);
// This is where it fails
final ResumableGDataFileUploader resumableGDataFileUploader = builder.build();
resumableGDataFileUploader.start();
return tempFile.length();
The "client" is an instance of DocsService, configured to use OAuth. It is used to find "documentListEntry" immediately before the given piece of code.
I had to explicitly specify request type, since it seems the client library code contains a bug causing NullPointerException for "update existing entry" case.
I have a suspicion that the issue is specifically in the sequence of actions (upload 0-byte file to get the resourceId, then update with actual file) but I can't figure out why it doesn't work.
Please help?
This code snippet works for me using OAuth 1.0 and OAuth 2.0:
static void uploadDocument(DocsService client) throws IOException, ServiceException,
InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(10);
File file = new File("<PATH/TO/FILE>");
String mimeType = DocumentListEntry.MediaType.fromFileName(file.getName()).getMimeType();
DocumentListEntry documentEntry = new DocumentListEntry();
documentEntry.setTitle(new PlainTextConstruct("<DOCUMENT TITLE>"));
int DEFAULT_CHUNK_SIZE = 2 * 512 * 1024;
ResumableGDataFileUploader.Builder builder =
new ResumableGDataFileUploader.Builder(
client,
new URL(
"https://docs.google.com/feeds/upload/create-session/default/private/full?convert=false"),
new MediaFileSource(file, mimeType), documentEntry).title(file.getName())
.requestType(RequestType.INSERT).chunkSize(DEFAULT_CHUNK_SIZE).executor(executor);
ResumableGDataFileUploader uploader = builder.build();
Future<ResponseMessage> msg = uploader.start();
while (!uploader.isDone()) {
try {
Thread.sleep(100);
} catch (InterruptedException ie) {
throw ie; // rethrow
}
}
DocumentListEntry uploadedEntry = uploader.getResponse(DocumentListEntry.class);
// Print the document's ID.
System.out.println(uploadedEntry.getId());
System.out.println("Upload is done!");
}

Resources