I am seeing this:
https://vertx.io/docs/kdoc/vertx/io.vertx.rxjava.core.http/-http-server-response/set-chunked.html
vertx.createHttpServer()
.requestHandler(req -> {
if (req.method() == HttpMethod.GET) {
req.response().setChunked(true);
}
})
I would assume chunked is true by default but I can't find the default value in the docs. Does anyone know what the default value is?
setChunked sets the transfer-encoding header to chunked.
When you send some content to the client with the write method, Vert.x verifies that either the transfer-encoding or the content-length header is set.
Do add on the previous answer, you can see the actual code here:
https://github.com/eclipse-vertx/vert.x/blob/f68ae15171053d343590e54884ec377f095ba6b3/src/main/java/io/vertx/core/http/impl/HttpServerResponseImpl.java#L142
public HttpServerResponseImpl setChunked(boolean chunked) {
synchronized (conn) {
checkValid();
// HTTP 1.0 does not support chunking so we ignore this if HTTP 1.0
if (version != HttpVersion.HTTP_1_0) {
headers.set(HttpHeaders.TRANSFER_ENCODING, chunked ? "chunked" : null);
}
return this;
}
}
Related
I'm currently trying to build a contract like this:
Contract.make {
description("""
Represents a successful scenario of getting an account
```
given:
account id
when:
api request for an account
then:
return account
```
""")
request {
method 'GET'
urlPath(regex("/api/v1/account/" + anyNumber()))
}
response {
status 200
body(
accountNumber: value(anyNumber())
)
headers {
contentType(applicationJson())
}
}
}
But getting an exception
cloud:spring-cloud-contract-maven-plugin:4.0.0:generateTests failed: java.util.regex.PatternSyntaxException: Illegal repetition near index 34
[ERROR] /api/v1/account/ClientDslProperty{
[ERROR] clientValue=-?(\d*\.\d+|\d+),
[ERROR] serverValue=-90366052}
[ERROR] ^
If reading the documentation here this should be possible.
If I use hardcoded values it works e.g.
Contract.make {
description("""
Represents a successful scenario of getting an account
```
given:
account id
when:
api request for an account
then:
return account
```
""")
request {
method 'GET'
url '/api/v1/account/1234'
}
response {
status 200
body("""
{
"accountNumber": "${value(1234)}"
}
""")
headers {
contentType(applicationJson())
}
}
}
Can someome help me out please? Thanks a lot in advance
Spring Cloud Contract is new to me, but reading the documentation (https://cloud.spring.io/spring-cloud-contract/reference/html/project-features.html#contract-dsl-regex) suggests that when you define the request with a regex, you should be specifying that it's for the consumer side. Also, anyNumber() doesn't return a simple string that can be concatenated into a regex pattern like you've done. I think you want something like this:
url value(consumer(regex('/api/v1/account/\d+')))
Then, to reference the number in your response section, you probably want something like:
body(
accountNumber: fromRequest().path(3)
)
(this is from the section of documentation that you linked to in your question)
I am getting a CORS error when I try to use my HTTP Delete method.
My Frontend is Angular-ionic and my Server is a Java server. Both are self-made.
I tried to disable CORS in the Browser, by doing so I managed the Request to work and the Error to disappear. Although that's fine, my goal is to make it work every time for EVERY user.
Here is my Code with a bit of Background:
console.log('User Management Service Delete User()');
const myParams = new HttpParams().set('id', this.cookieService.get('AccessToken'));
console.log(myParams);
return this.http.delete(this.endpoint + 'users/delete', { params: myParams});
}
The code above is my FRONTEND (clientside) code. I am simply trying to delete a user.
public int serveUserDelete(HTTPServer.Request req, HTTPServer.Response resp) throws IOException {
Map<String, String> params = req.getParams();
String response;
String paramvalue;
String accessToken;
resp.getHeaders().add("Content-Type", "application/json");
resp.getHeaders().add("Access-Control-Allow-Origin", "*");
resp.getHeaders().add("Access-Control-Allow-Headers", "*");
resp.getHeaders().add("Access-Control-Allow-Credentials", "true");
resp.getHeaders().add("id", "*");
resp.getHeaders().add("Access-Control-Allow-Methods", "OPTIONS, DELETE, POST, GET, PATCH, PUT");
response = "";
//Id aus dem Parameter auslesen
if (params.containsKey("id")) {
//es gibt einen Parameter id. Suche den Wertd dazu
accessToken = params.get("id");
System.out.println(accessToken);
} else {
accessToken = null;
}
response = um.userDelete(accessToken);
resp.send(200, response);
return 0;
}
The Code above now, is my Java server.
The headers were added cause of trial and error.
Here the error I am getting:
Access to XMLHttpRequest at 'http://localhost:8080/umyServerUrl/users/delete?id=u#Yy0NZPLx%266HxYNF%23tv'
from origin 'http://localhost:8100' has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
No 'Access-Control-Allow-Origin' header is present on the requested resource.
threw testing (with disabled browser cors etc.) I found out that the methods on my server work just fine.
Here you can see my "PARAMS" and the Observable of my delete Request printed in the Console:
HttpParams
{updates: Array(1),
cloneFrom: HttpParams,
encoder: HttpUrlEncodingCodec,
map: null}
cloneFrom:
nullencoder:
HttpUrlEncodingCodec {}[[Prototype]]:
Objectconstructor: class
HttpUrlEncodingCodecdecodeKey: ƒ
decodeKey(key)decodeValue: ƒ
decodeValue(value)encodeKey: ƒ
encodeKey(key)encodeValue: ƒ
encodeValue(value)[[Prototype]]:
Objectmap:
Map(1)[[Entries]]0: {"id" => Array(1)}
key: "id" value: ['hTxYusBwuB7pbUUCkW9E']size: 1[[Prototype]]:
Mapupdates: null[[Prototype]]:
Object
user-management.service.ts:35
**Oberservabel:**
Observable {_isScalar: false, source: Observable,
operator: MapOperator}
operator: MapOperator
project: res => res.body
length: 1
name: ""
arguments: (...)
caller: (...)
[[FunctionLocation]]: http.mjs:1300
[[Prototype]]: ƒ ()
[[Scopes]]: Scopes[2]
thisArg: undefined
[[Prototype]]: Object
call: ƒ call(subscriber, source)
constructor: class MapOperator
[[Prototype]]: Object
source: Observable
operator: FilterOperator {thisArg: undefined, predicate: ƒ}
source: Observable {_isScalar: false, source: Observable, operator: MergeMapOperator}
_isScalar: false
[[Prototype]]: Object
_isScalar: false
[[Prototype]]: Object
PLEASE HELP
This combination of Access-Control headers is invalid.
resp.getHeaders().add("Content-Type", "application/json");
resp.getHeaders().add("Access-Control-Allow-Origin", "*");
resp.getHeaders().add("Access-Control-Allow-Headers", "*");
resp.getHeaders().add("Access-Control-Allow-Credentials", "true");
You cannot set Access-Control-Allow-Origin to * and also allow Access-Control-Allow-Credentials.
For requests without credentials, the literal value "*" can be specified as a wildcard; the value tells browsers to allow requesting code from any origin to access the resource. Attempting to use the wildcard with credentials results in an error.
This might be a large scale issue of the system architecture.
For now you could test setting the Allow-Origin header like this:
resp.getHeaders().add("Access-Control-Allow-Origin", "http://localhost:8100");
However if it's supposed to work from an arbitrary number of clients another architecture might be necessary.
CORS is a security feature. Do not "trial and error" around with security features!
I'm working on Lagom POC on sending POST request to Non lagom service with custom Header. In my case I'm trying to hit postman-echo to test the custom header.
However, it looks the headers are not set though I made code changes accordingly:
public CompletionStage<DsapAuthorizationResponse> hitAPI(AuthorizationRequest request) {
DsapWSRequest dsapWSRequest = new DsapWSRequest();
dsapWSRequest.username = request.username;
dsapWSRequest.password = request.password;
CompletionStage<DsapAuthorizationResponse> dsapresponse = dsapExternalService
.authenticate()
.handleRequestHeader(requestHeader -> {
requestHeader.withHeader("Authorization","Basic mncndsjna");
System.out.println("My Headers>>>>>>>> " + requestHeader);
return requestHeader;
})
.handleResponseHeader((responseHeader,b) -> {
System.out.println("RESPonse Header >>>>>>> : "+responseHeader);
return b;
})
.invoke(dsapWSRequest);
return dsapresponse;
}
In the above code header authorization is not set in the request. I am not getting this header in the echo which is mapped correctly in my POJO.
here is the complete code from my GitHub
https://github.com/sourabhsar/Lagom-Unmanaged-Service-Demo/tree/poc/lagom-request-response
I followed the steps mentioned here:
https://groups.google.com/forum/#!topic/lagom-framework/yvKmqvtZWFs
and also followed few other blogs/articles.
However so far I haven't found any blog which they are sending request to unmanaged external service with custom header. I'm not sure whats wrong in my code.
requestHeader.withHeader returns a new object with the added header, but the code you have written returns the original requestHeader object. In general, many Lagom APIs follow a principle of using immutable objects, with methods that return a new, modified instance, rather than changing the instance the method is called on.
Try this:
.handleRequestHeader(requestHeader -> {
RequestHeader modifiedRequestHeader =
requestHeader.withHeader("Authorization","Basic mncndsjna");
System.out.println("My Headers>>>>>>>> " + modifiedRequestHeader);
return modifiedRequestHeader;
})
In Spring I set some cookies I need for my websocket:
Cookie ck = new Cookie("session", request.getSession().getId());
ck.setDomain(".mydomain.com");
ck.setPath("/");
ck.setVersion(1);
Cookie secretCookie = new Cookie("scrt", secret);
secretCookie.setDomain(".mydomain.com");
secretCookie.setPath("/");
secretCookie.setVersion(1);
response.addCookie(secretCookie);
response.addCookie(ck);
But when I read the header of the websocket handshake, the value of the cookie field only consists of a string which looks like this:
session=foobar; scrt=foomart
When you try to parse this value by HttpCookie.parse(); the HTTPCookie will try to identify the version of the cookie.
private static int guessCookieVersion(String header) {
int version = 0;
header = header.toLowerCase();
if (header.indexOf("expires=") != -1) {
// only netscape cookie using 'expires'
version = 0;
} else if (header.indexOf("version=") != -1) {
// version is mandatory for rfc 2965/2109 cookie
version = 1;
} else if (header.indexOf("max-age") != -1) {
// rfc 2965/2109 use 'max-age'
version = 1;
} else if (startsWithIgnoreCase(header, SET_COOKIE2)) {
// only rfc 2965 cookie starts with 'set-cookie2'
version = 1;
}
return version;
}
If the Value is 0, which is wrong but the case here, the HttpCookie will only parse the first entry.
If you force version to be 1, this won't work either, since HttpCookie is expecting comma seperated values. splitMultiCookies(String header)
Is there any way to fix this but writing my own parser?
It is funny because a cookie has no field "version" anymore. I can find a reference to it in the RFC2109 (1997), but it is not there anymore in RFC6265 (2011). Actually, the cookie API in .NET does not provide a built-in method to set such property (that is the reason this caught my attention). Check that the browser is actually sending that data as part of the handshake, maybe the browser is ignoring it.
I can't seem to figure out how to add headers to my restlet response. When I look at the available methods in the Response object, all I see is setStatus, setEntity, and setAttributes but none of these tell me how to set custom http headers on the response.
For example, I have a GET call the returns something like the following:
HTTP/1.1 200 OK
Content-Type: text/json
Content-Length: 123
Some-Header: the value
Some-Other-Header: another value
{
id: 111,
value: "some value this could be anything",
diagnosis: {
start: 12552255,
end: 12552261,
key: "ABC123E11",
source: "S1",
}
}
Whatever it maybe. In the handleGet method, I handle it like so:
final MediaType textJsonType = new MediaType("text/json");
#Override
public void handleGet() {
log.debug("Handling GET...");
final Response res = this.getResponse();
try {
final MyObject doc = this.getObj("hello", 1, "ABC123E11", "S1");
final String docStr = doc.toString();
res.setStatus(Status.SUCCESS_OK);
res.setEntity(docStr, textJsonType);
// need to set Some-header, and Some-other-header here!
}
catch(Throwable t) {
res.setStatus(Status.SERVER_ERROR_INTERNAL);
res.setEntity(new TextRepresentation(t.toString()));
}
}
Because Restlet is more about the REST architectural principles than HTTP, it tries to be protocol agnostic and doesn't expose the HTTP headers directly. However, they are stored in the org.restlet.http.headers attribute of the response (as a Form). Note that you can only set custom headers this way, not standard ones (these are handled directly by the framework, e.g. Content-Type depends on the Representation's MediaType).
See this for an example:
http://blog.arc90.com/2008/09/15/custom-http-response-headers-with-restlet/ (link content also available from the Internet Archive Wayback Machine).