I have no problem making NIFI post type requests. In the articles I've seen, I used the "invokeHTTP" component, with a "post" configuration inside it. I need to send a JSON to a fixed address, and invokeHTTP does not work. You can do the same thing with POSTMAN and it works, however in NIFI I can not.
I placed the request body in the "Put Response Body In Attribute" field.
The design can be done with CORS do not disturb (The project and the NIFI are in local network, in port 8081 and 8088 respectively).
I would like to know if anyone has any hints as to why my project does not receive a NIFI request, but receives from POSTMAN. Can I, be setting something wrong ...
I think the issue is the request body. It sounds like you are putting the request body in the attribute specified in the Put Response Body In Attribute property.
For InvokeHTTP the flowfile contents are included as the body of the request.
Place the JSON you want to send via an HTTP POST in the content of the flowfile prior to the flowfile reaching your InvokeHTTP processor.
The Put Response Body In Attribute property specifies that the HTTP response body should be written to a named flowfile attribute as part of the input flowfile (rather than the default behavior, which is to generate a new output flowfile with the content of the HTTP response).
Related
I am calling an API, that blacklists certain HttpHeaders including Content-Length which seems to be preset by the HttpClient underneath spring-openfeign.
To properly receive an API response, I'd need to remove the Content-Length header.
The following workarounds had been tried:
I tried to set the header to null or an empty String using the available Feign annotations #Headers, #RequestHeaders
I implemented a RequestInterceptor that creates a copy of the available (immutable) header map, deletes the blacklisted header and sets the Map as requestTemplate.headers(newHeaders). But only new headers can be added and the available ones not modified (seems to be really immutable ;))
I researched on overriding the used HttpClient but wasn't successful until now.
Experienced errors/ issues:
The API I am calling returns a 400 based on their header schema validation.
Code:
In case any code-snippets are needed, I am happy to provide them but to me the issue does not seem to be related to any code issue as I am not running into any exceptions.
Thanks in advance!!
The Apache Http Client included in feign-httpclient will always set the content length header if there is a request body present. One way to address this to configure the Apache Client directly and provide it to Feign via the builder:
This custom client can have an Apache Http Client interceptor applied that allows you to modify the request after it leaves Feign and before Apache sends it. Review their javadoc for more information.
public class Example {
public static void main(String[] args) {
HttpClient httpClient = HttpClients.custom.build();
GitHub github = Feign.builder()
.client(new ApacheHttpClient(httpClient))
.target(GitHub.class, "https://api.github.com");
}
}
FeignClient will preset Content_Length in the request header. In a keep-alive connection mode, either Content-Length or Transfer-Encoding header field must be set to signal the presence of a message body, so you can set Transfer-Encoding=chunked and Content-Length will be ignored by the serverside.
You can refer to rfc7230#section-3.3.1
"The presence of a message body in a request is signaled by a
Content-Length or Transfer-Encoding header field. Request message
framing is independent of method semantics, even if the method does
not define any use for a message body."
"In order to remain persistent, all messages on a connection need
to have a self-defined message length (i.e., one not defined by
closure of the connection), as described in Section 3.3. A server
MUST read the entire request message body or close the connection
after sending its response, since otherwise the remaining data on a
persistent connection would be misinterpreted as the next request.
Likewise, a client MUST read the entire response message body if it
intends to reuse the same connection for a subsequent request."
and from here , you can read:
"All HTTP/1.1 applications that receive entities MUST accept the
"chunked" transfer-coding (section 3.6), thus allowing this mechanism
to be used for messages when the message length cannot be determined
in advance.
Messages MUST NOT include both a Content-Length header field and a
non-identity transfer-coding. If the message does include a non-
identity transfer-coding, the Content-Length MUST be ignored.
When a Content-Length is given in a message where a message-body is
allowed, its field value MUST exactly match the number of OCTETs in
the message-body. HTTP/1.1 user agents MUST notify the user when an
invalid length is received and detected."
even though i have appended my service response with following provided CORS Headers :
resp.setContentType("application/json");
resp.addHeader("Access-Control-Allow-Origin", "*");
resp.addHeader("Access-Control-Allow-Credentials", "true");
resp.addHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS");
resp.addHeader("Access-Control-Allow-Headers", "Origin,accept,content-type");
resp.flushBuffer();
i am still getting below error in the console while trying to access some of the POST web methods in the service through my AngularJS frontend.
XMLHttpRequest cannot load http://192.***.*.***:8080/abc/def/search/vehicleManufacturer. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://192.***.*.***:8085' is therefore not allowed access.
However within the same class, some POST methods without any payloads are responding perfectly. Any suggestions ?
EDIT--------->
Below is my AngularJS client screen code for calling the web method:-
getVehicleModel : function(searchData,$scope){
$http({
method:'POST',
url:'http://192.169.*.***:8085/abc/def/search/vehicleModel',
dataType:'jsonp',
data:searchData
}).
success(function(data){
console.log("vehicle model")
$scope.vehicleModel = data.Response;
});
},
I think the problem here is Preflighted Requests in CORS.
From the Mozilla docs,
Unlike simple requests (discussed above), "preflighted" requests first
send an HTTP request by the OPTIONS method to the resource on the
other domain, in order to determine whether the actual request is safe
to send. Cross-site requests are preflighted like this since they may
have implications to user data. In particular, a request is
preflighted if:
It uses methods other than GET, HEAD or POST. Also, if POST is used to send request data with a Content-Type other than
application/x-www-form-urlencoded,
multipart/form-data
text/plain
e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)
As explained above, even though you're making a simple POST request, the Content-Type in your request is application/json which is different from the 3 types mentioned above, so it's considered as a Preflight request and an OPTIONS request is fired before your actual POST request.
You can solve this by implementing doOptions in your servlet, just add the headers there and it will work :)
The preflight (OPTIONS) is occurring due to the fact that you are sending a cross-origin ajax request AND specifying an Authorization header with this GET request.
Also (this is not causing an issue) I would suggest removing the contentType option. This doesn't make sense in the context of a GET request. A GET request should not have any content. All data should be included in the query string or, possibly, headers.
The Authorization header will not be sent with the OPTIONS. You must acknowledge it server-side, and then the browser will send the underlying GET. Read more about CORS at https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS .
In a java web-app I write to my HttpServletResponse:
httpResponse.getWriter().write(someJsonString);
httpResponse.getWriter().flush();
The client (apache jmeter in this case) gets the response with the json in the body and status 200 as expected.
If I decide to change the response status:
httpResponse.getWriter().write(someJsonString);
httpResponse.setStatus(Response.Status.NO_CONTENT.getStatusCode());
httpResponse.getWriter().flush();
My client gets the response with the right status (204 in this case) but an empty body for some reason.
What can cause this?
When you send response as 204, it means there is no body.
See w3c rfc
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
It means while sending response either container is not considering body or your client is discarding after reading status in response.
One way could be to check this response in web-browser if possible. With tools like fire-bug or similar in Chrome you could actual check response.
Is it possible to send HTTP POST request to a webserver and retrieve just headers of response or read just few bytes of the body, so the rest won't be downloaded at all (so it won't consume traffic)? If yes, how?
I know that there is a HEAD method for this, but I need to achieve it by POST method .. well, I am not sure if I need the POST method, I just need to post the data. Maybe if the webserver isn't secured well enough (it doesn't check what method it's used - it's just directly access the post data), is it possible to send "post data" by HEAD request?
There is no built-in HTTP mechanism for this, and HTTP HEAD requests do not allow content in the body. If however you are the one writing the server code then anything is possible.
If this is the case, I would suggest a URL parameter that triggers this behavior. For example:
POST /myURL - This would return the whole response
POST /myURL?body=minimal - Returns the reduced size response that you are looking for.
And you would have to code your server method to construct and return the appropriate response based on the URL parameter.
im writing a java application that sends a post request to a server and expect a json from the server. Now when i need to get the response from the server do i only need to get it from the inputStream when the http code is 200 (HTTP OK) or is there any other cases ? , example :
//...
if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) {
// only here try to get the response
}
//...
It depends on how the server is implemented. Check the API, if the server has one. If it's internal, ask your server guy.
Generally speaking, if your response code is either 2xx or 3xx, I would check the response anyway...
If the server your communicating with is following the spec then either 200 or 201 responses are valid to contain an entity. A 204 response is successful but has no data in the response.
See section 9.5 here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.5 for details of acceptable responses to a POST. Extract below:
The action performed by the POST method might not result in a resource
that can be identified by a URI. In this case, either 200 (OK) or 204
(No Content) is the appropriate response status, depending on whether
or not the response includes an entity that describes the result.
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see section 14.30).
There are three things to consider:
All 2xx codes denote success of some sort. But depending on the exact code, your reading code might be different. (204 for example means success but no content.)
There are redirecting codes (3xx). These are usually automatically followed by the http client library but you can also set them not to, in which case you need to have custom code that handles these cases.
There can be valuable information returned in the stream even if you get a code that denotes an error. Whether you want to process it depends on your exact needs.