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).
Related
Forgive my ignorance - a jr developer here. I'm trying to make a PUT call to a client API. In the documentation it shows the request headers have an object in them. I thought headers could only have a String value. How can I add an object to my HttpHeaders object?
Request Model from API Documentation
requestHeader {
"headerA": "valueA",
"headerB": {
"headerB1": "valueB1",
"headerB2": "valueB2"
},
"headerC": "valueC"
}
requestBody {
"object": {
"variable1": 12345,
"variable2": 54321
},
"sameNums": false }
I'm using HttpHeaders from package org.springframework.http - the set() and add() methods take Strings as parameters. How can I add an object as a header value?
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 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;
}
}
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;
})
I'm trying to make a POST request using JavaScript routing. In the routes file:
POST /comments controllers.Clients.addComment(text: String, client: Int)
GET /assets/javascripts/routes controllers.Application.javascriptRoutes()
on page:
jsRoutes.controllers.Clients.addComment(args.text, #client.id).ajax(...);
But it creates the request
POST http://localhost:9000/comments?text=qwe&client=1 HTTP/1.1
How do I make it pass parameters in the POST body instead of a request string?
Tak a look at ajax() documentation - that is, such example:
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
});
As Play JavaScript route already defines url and request method (type), you need only to add data (of course you don't need to specify them as a params in brackets)
jsRoutes.controllers.Clients.addComment().ajax(
data: {
client: #client.id,
text: args.text
}
);
Also you can send a text only to given client (determined by the URL (it can be POST but PUT looks nicer :)):
PUT /comments/:client controllers.Clients.addComment(client: Int)
in the view:
jsRoutes.controllers.Clients.addComment(#client.id).ajax(
data: { text: args.text }
);
So it will perform PUT request to http://domain.tld/comments/123 and text will be available in the form() as it was sent with POST:
public static Result addComment(int client) {
String receivedText = form().bindFromRequest().get("text");
// save it to DB ...
return ok( "Added comment: "+ receivedText+ ". for client id: " + client);
}
As i don't quite understand the JsRoutes in Play, what i did was:
In my view:
var client = 1;
$.ajax({
type: "POST",
url: "/comments/" + client,
});
And in my routes, the call to the method:
GET /comments/:client controllers.Clients.addComment(client: Int)
This works letting the browser make the request like a normal ajax call to some URL defined in routes.