I would try to create an API Rest client for a code that I have in a GWT project.
In order to arrive to the server and obtain a response I need to attach some custom headers in my request.
I saw, there were some bugs some years ago when write headers in the request.
Actually, I have this code, and I don't know exactly where and when put my custom header in the request.
final Map<String, String> headers = new HashMap<String, String>();
headers.put("X-USER", "super_admin_key");
Resource resource = new Resource("http://localhost:9998/api/v1/", headers);
ServicesAPI service = GWT.create(ServicesAPI.class);
((RestServiceProxy)service).setResource(resource);
REST.withCallback(new MethodCallback<String>(){
#Override
public void onFailure(org.fusesource.restygwt.client.Method method, Throwable exception) {
domainsCombo.addItem("ERROR");
}
#Override
public void onSuccess(org.fusesource.restygwt.client.Method method, String response) {
domainsCombo.addItem("ok");
}
}).call(service).getServices();
Add headers to the resource object creation is one of the options, but it doesn't work.
Any sugestion?
Thanks.
Related
I'm developing a flutter app using Grpc to connect to the server. Some of the services need extra metadata for authentication, so the first thing that comes to my mind is implementing an interceptor to add the metadata to those requests like this:
class MyClientInterceptor implements ClientInterceptor {
#override
ResponseFuture<R> interceptUnary<Q, R>(ClientMethod<Q, R> method, Q request, CallOptions options, invoker) {
var newOptions = CallOptions.from([options])
..metadata.putIfAbsent('token', () => 'Some-Token');
return invoker(method, request, newOptions);
}
}
But I get Caught error: Unsupported operation: Cannot modify unmodifiable map because CallOptions uses an unmodifiable map.
First question: What is the best practice to add authentication to some of the requests instead of creating the Client stub with those metadata?
Second: How can I copy the metadata from options, modify it and use the modified object?
First question: What is the best practice to add authentication to some of the requests instead of creating the Client stub with those metadata?
Some AUTH libs which I saw use metadata to provide authentication token/key etc.
For example https://github.com/grpc/grpc-dart/blob/master/lib/src/auth/auth.dart#L43
So do not hesitate to add your custom auth header in metadata dict. In can be done via interceptor as you did or via CallOptions:
final resp = await _grpcClient.someApiCall(req,
options: CallOptions(metadata: {'auth': 'your token'}));
Second: How can I copy the metadata from options, modify it and use the modified object?
Just clone previous CallOptions with new value via mergedWith
Second question:
class MyClientInterceptor implements ClientInterceptor {
#override
ResponseFuture<R> interceptUnary<Q, R>(ClientMethod<Q, R> method, Q request, CallOptions options, invoker) {
var newOptions = options.mergedWith(
CallOptions(
metadata: <String, String>{
'token': 'Some-Token',
}
)
);
return invoker(method, request, newOptions);
}
}
Is it possible to remove response headers with a RestFilter? Looking at this cookbook you would say it should be possible. However, the filter is only called when the request is incoming, before the call to the resource class. I was expecting to have a hook where I can modify the response headers before sending it back to the client.
i had a look at CORSFilter as an example, but it only sets headers, not remove them.
To be more specific, I want to remove the WWW-Authenticate header that is set by the Auth provider when the session has expired. This header causes a popup in the browser (chrome) that is undesirable.
what you need is a javax.ws.rs.container.ContainerRequestFilter. In jax-rs such filters can be registered in a javax.ws.rs.core.Application. The application used in ICM is com.intershop.component.rest.internal.application.DefaultRestApplication which can be adapted using an com.intershop.component.rest.internal.application.ApplicationClassesProvider that can be registered using a Set-Binding.
So you could create a Guice-Module and your filter:
public class MyRestModule extends AbstractModule
{
#Override
protected void configure()
{
Multibinder<ApplicationClassesProvider> binder = Multibinder.newSetBinder(binder(),
ApplicationClassesProvider.class);
binder.addBinding().toInstance(c->c.accept(MyResponseFilter.class));
}
}
public class MyResponseFilter extends ContainerRequestFilter
{
#Override
public void filter(ContainerRequestContext request, ContainerResponseContext response)
{
response.getHeaders().remove("WWW-Authenticate");
}
}
Please note that this filter will be applied to all requests, so please make sure you remove headers only for requests you really care about.
We need to set below response headers in CQ5/AEM based application.
Http Header: Frame options Set X-Frame-Options: SAME ORIGIN
Http Header: Strict Transport Security Strict-Transport-Security: max-age=10886400; includeSubDomains; preload
I have done like these changes in my prior application using servlet filter to intercept the request. Similarly I tried to use the SlingFilter for this application. However it seems to be called many times for each request (when it download js,css,json files etc). Please see below code snippet,
#SlingFilter(scope = SlingFilterScope.COMPONENT, order = Integer.MIN_VALUE)
#Properties({
#Property(name="pattern",value="/soni/template/", propertyPrivate=false)
})
public class ResponseHeaderFilter implements Filter {
#Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
try {
HttpServletResponse httpResponse = (HttpServletResponse)response;
httpResponse.setHeader("Strict-Transport-Security", "max-age=10886400; includeSubDomains");
filterChain.doFilter(request, httpResponse);
httpResponse.setHeader("X-Frame-Options", "SAMEORIGIN");
} catch (Exception e) {
e.printStackTrace();
}
}
Is this the right way to do it in CQ5/AEM? How do I restrict this to once per page request?
or is there better way to do it like configuration at dispatcher etc?
Because you are using the Component scope, this filter is called every time you include a component, which is not your intention.
Please use request scope:
scope = SlingFilterScope.REQUEST
Refer to this page:
https://sling.apache.org/documentation/the-sling-engine/filters.html
I need to create a RESTful service which should support async calls in follwing way. When user calls some method he got the http '202' code and url to poll where he can see the status of his request. Currently I use JAX-RS and its annoations:
#Path("")
public interface MyService {
#POST
#Path("/myService/{name}")
#Consumes({APPLICATION_XML, APPLICATION_JSON})
void postSomething(#PathParam("name") String name, MyObject data);
}
Such mapping would expose MyService's postSomething() method by url /myService/{name} which serves POST requests, get 'name' parameter from url and 'data' from request body.
I want that after making this PUT request client get 202 http code and some callback url to poll to get the result once method will be executed.
So the question is:
1. How to make JAX-RS return 202 code?
2. How to pass callback url to the client?
Have the postSomething method return a Response object:
public Response postSomething(#PathParam("name") String name, MyObject data) {
return Response.status(Status.ACCEPTED).build();
}
If you want the callback URI as plain-text in the HTTP Body you could do something like this:
public Response postSomething(#PathParam("name") String name, MyObject data) {
return Response.status(Status.ACCEPTED).entity("http://google.com").build();
}
For generating URIs by resource classes, have a look at UriBuilder
Use #Context HttpServletResponse servletResponse to get direct control over the servlet's response mechanism.
#PUT
#Path("/myService/{name}")
#Consumes({APPLICATION_XML, APPLICATION_JSON})
void postSomething(#PathParam("name") String name, #Context HttpServletResponse response, MyObject data) {
// ...
response.setStatus(HttpServletResponse.SC_ACCEPTED);
response.setHeader("Location", myURL);
// ...
}
I have an interceptor like this:
public class WebServiceInterceptor extends EndpointInterceptorAdapter {
#Inject
private Jaxb2Marshaller myJaxb2Marshaller;
#Inject
private WebServiceHistoryDao webServiceHistoryDao;
#Override
public boolean handleRequest(MessageContext messageContext, Object endpoint)
throws Exception {
Source payloadSource = messageContext.getRequest().getPayloadSource();
Object unmarshaled = myJaxb2Marshaller.unmarshal(payloadSource);
//EXTRACT XML HERE
//is there a better way than this:
String extractedXml = myJaxb2Marshaller.marshal(unmarshaled);
return true;
}
}
How can i extract the whole xml of envelope (for logging purposes - to write it to the DB)
You don't need to write one, there's an existing one in the API - SoapEnvelopeLoggingInterceptor. See the javadoc.
SOAP-specific EndpointInterceptor that logs the complete request and response envelope of SoapMessage messages. By default, request, response and fault messages are logged, but this behaviour can be changed using the logRequest, logResponse, logFault properties.
If you only need to see the payload, rather than the entire SOAP envelope, then there's PayloadLoggingInterceptor.