Thought this would be a common use case but I'm coming up short. Also, I'm using Scala but a Java answer would be fine, too.
In Jersey I'd like to set a simple cookie on all responses coming out of my app.
A quick google shows that I can set cookies on a single response by performing the following:
return Response.ok(new Viewable("/index", model))
.cookie(new NewCookie("name", "Hello, world!"))
.build();
That's great if I just want to set a cookie on a per-response basis, but I want it on every response. This seems like a job for middleware. The Jersey Docs recommend this for setting up middleware:
class MyResponseMiddleware ContainerResponseFilter {
override def filter(req: ContainerRequestContext, res: ContainerResponseContext) = {
// do stuff here
}
}
The problem is there's no way to set a cookie on the ContainerResponseContext as .getCookies returns a read-only map, unlike .getHeaders() which is mutable.
I also tried to create a cookie by setting the headers:
containerResponseContext.getHeaders().add(HttpHeaders.SET_COOKIE, new NewCookie(...)) but this did not make it to the browser.
It seems like if I could get a reference to ServletResponse or HttpServletResponse this would be simple but that doesn't appear to be possible in Jersey's middleware (filters).
This seems like a pretty straightforward use-case so I feel like I'm missing something obvious.
You can simply Inject HttpServletResponse into the filter.
Use #Context annotation as follows.
#Provider
public class ResponseHTTPStatusFilter implements ContainerResponseFilter{
#Context HttpServletResponse resp;
#Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
resp.addCookie(cookie);
}
}
Related
I am trying to make an API with Jetty Server, and I have this simple GET request:
#GET
public String helloWorld(){
return "Hello world";
}
In order to make a POST request, I assume that one must save the input to the Jetty server. I have tried to research for quite a while, but found nothing.
I imagine something like this:
#POST
public void Save(String stringToSave) {
// Save to DB?
}
You could likely google this but let me give you a quick overview. A Servlet is a chunk of code that is normally run during an HTTP action - GET, POST, etc. It is the original technology of the JavaEE world, having been released in the late 1990's.
A simple Java servlet, using modern annotations, would look something like:
#WebServlet(name = "SampleServlet", urlPatterns = "/sampleServlet")
public class SampleServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// called when an HTTP POST is sent
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// called when an HTTP GET is sent
}
}
The important parts to note are that the class extends HttpServlet and that you have to write code to pull data out of the request and push it into the response. This isn't bad to do but it does have to be done.
JAX-RS is a newer standard, aimed simplifying the creation of REST services. It too is a chunk of code that runs during an HTTP interaction.
A simple example of this would be:
#Path("/sampleService")
public class SampleService{
#Consumes({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML})
#POST
#Path("/v1/hello")
public Response sayHello( SomeObject someobject ) {
The code here is both simpler and a bit more complex. The use of annotations helps determine the path that the service exists on a URL (in this case /sampleService/v1/hello), the HTTP method, and the Content-Type for both the request and response. Additionally, if the SomeObject object is defined correctly, the JAX-RS framework will automatically deserialize the incoming JSON or XML payload into an object for you.
The Response object contains the HTTP response code (perhaps a teapot) and a response body. In this example, the body will be automatically serialized back to the requestor in a way that matches the Accept header of the HTTP request (i.e., JSON for an application/json Accept header and XML for application/xml).
Note that while not directly related the JAX-RS framework takes advantage of the Servlet framework. Indeed in JAX-RS you can access the HttpServletRequest and HttpServletResponse object in your methods.
Which way is "better"? In general I would recommend using JAX-RS where possible as it is the newer standard and is a bit easier to implement. However, if you do any work in the JavaEE world you're very likely to run into Servlet code so it's important to understand it too.
Note that both Servlets and JAX-RS require an application server of some sort. Jetty is one of those. Another very common one is Tomcat. The application server sets up the environment for your code and listens for incoming HTTP messages. When it gets one it looks to see if it knows how to handle the URL and routes to the appropriate place. In the servlet world the server routes solely on the URL. In the JAX-RS world the server routes on the URL and, if specified by the #Consumes annotation, the HTTP Content-Type header too.
There is much more but let's start there and see if it answers what you're after.
I have a spring boot application running with a graphql endpoint that validates and executes queries and mutations, however, I need to read one header in the incoming message in order to pass its value to another endpoint. Is there a way in graphql to read these values? some sort of getHeaders or something like that?
GraphQL itself does not define any things related to how to expose it over the network , so it does not define any things related to get HTTP header.It is up to developers to use their ways.So, it depends on the underlaying technologies you use to serve GraphQL over HTTP.
Consider you use graphql-spring-boot and graphql-java-tools , and assuming that you does not customize GraphQLContext , you can try to add DataFetchingEnvironment argument to your resolver function and then get the GraphQLContext from it. You can then get HttpServletRequest from the context and access the headers :
public Foo resolveFoo(Map<String,String> input , DataFetchingEnvironment env){
GraphQLContext context = env.getContext();
HttpServletRequest request = context.getHttpServletRequest().get();
request.getHeader("content-type");
}
The solution by #Ken Chan was not working for me. GraphQLContext had no method named getHttpServletRequest.
Solved it by using GraphQLServletContext instead. You can change the code to:
public Foo resolveFoo(Map<String,String> input , DataFetchingEnvironment env){
GraphQLServletContext context = env.getContext();
String header = context.getHttpServletRequest().getHeader("content-type");
}
Apparently the type of the context is not standardized. I use SPQR, and in my case I discovered (via debug):
DefaultGlobalContext<ServletWebRequest> context = handlerParameters.getDataFetchingEnvironment().getContext();
context.getNativeRequest().getHeader("something");
Not a direct answer to your problem statement, but one can use a Filter to handle it before the request hits the resolver endpoints (if that's a requirement):
public class HeaderFilter implements Filter {
#Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) {
final HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
String headerVal= httpServletRequest.getHeader("<header string>");
try {
filterChain.doFilter(httpServletRequest, servletResponse);
} catch (IOException | ServletException e) {
//handle as you wish
}
}
These answers are too old, for latest versions. There are two ways (1) you can try to autowire one HttpServletRequest in your controller, such as
#Slf4j
#Controller
public class YourQueryController {
#Autowired
private HttpServletRequest request;
....
Then implement following logic to get header:
request.getHeader("Authorization")
(2) To make use of out-of-box support of RequestContextHolder over HTTP requests
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
val authorization = attributes.getRequest().getHeader("Authorization");
Google brought me this answer and unfortunately it was for Spring framework. Many use Spring framework but if you use Apache Tomcat with GraphQL integration like I do, you can do use this.
graphql.kickstart.servlet.context.DefaultGraphQLServletContext.DefaultGraphQLServletContext context = dataFetchingEnvironment.getContext();
jakarta.servlet.http.HttpServletRequest request = context.getHttpServletRequest();
String tokenBearer = request.getHeader("Authorization");
hth
I simply need to attach query parameters onto an outgoing request. (Java EE 7.0, JAX-RS 2.0)
In specifics, I currently using the RESTeasy Client ver 3.0.14, so I make my calls using the fancy interface-proxy system. I was attempting to produce something like this:
myapplication/api/path?timestamp=000
with:
#Provider
public class MyRequestFilter implements ClientRequestFilter {
#Context
private HttpServletRequest servletRequest;
public void filter(ClientRequestContext requestContext) throws IOException {
servletRequest.getParameterMap().put("timestamp", new String[]{
String.valueOf(new Date().getTime())
});
}
}
I made sure I was registering it with client.register(MyRequestFilter.class) as well. Feel free to ask questions. Thanks!
Credit to #peeskillet --
Rebuild the URI from the requestContext like this:
requestContext.setUri(UriBuilder.fromUri(requestContext.getUri()).queryParam("key", value).build());
You can now see the new query parameter with
requestContext.getUri().toString();
Again, verify that you register it when making the REST Client
client.register(MyRequestFilter.class);
I want to implement custom authorisation in my REST services using Jersey. This custom authorisation inspects annotations on methods as well as the actual parameters that a
method receives.
My jax-rs annotated method looks like:
#GET
#Path("customers")
#Requires(Role.CustomerManager)
public Customer getCustomer(#ParseFromQueryString #CheckPermission final Customer customer) {
// ...
}
The #ParseFromQueryString is an annotation that indicates Jersey (through an Injectable provider) to unmarshall a Customer from a query string. The code for that looks like:
public class QueryStringCustomerInjectable implements Injectable<Customer> {
public Customer getValue() {
final Customer customer = new Customer();
// ... a UriInfo was injected using the #Context annotation
// ... extract parameters from QueryString and use setters
return customer;
}
}
The #CheckPermission annotation indicates my custom authoriser that permissions are to be checked on a customer. Some users have access to information on some customers. Similarly, the #Requires annotation takes a role that the invoker should have. These are not java's security roles (Strings), rather, they are enum values.
Using Jersey's ResourceDebuggingFilter as a starting point, I have been able to get to the point of knowing which method will be invoked. However, I still haven't figured out how to determine which parameters will actually be used to invoke the method.
At the top of my head, I can think of two work arounds:
A Method interceptor using Guice + Jersey.
Code this logic in the QueryStringCustomerInjectable, but this seems a bit sloppy. It would be a class doing too much.
Yet, I would really like to do this using only Jersey / JAX-RS. I feel that I am so close!
Ideas? Pointers?
Thanks!
You should use Filters or Interceptors to handle all the information about method.
see Jersey Filter and Interceptors
For the Customer deserialization you could implement the javax.ws.rs.ext.ParamConverterProvider and register it into Jersey. Then you can inject it into your methods with #QueryParam("customer"). It's a bit more flexible since you can use it also with #BeanParam or #PathParam annotations.
Then you can use the ContainerRequestFilter. See as a reference how jersey does the Oauth1 for example OAuth1ServerFilter.
The next thing you can do is to create maybe a feature which will register the newly created filter (see Oauth1ServerFeature for a reference - I couldn't find the source code right now).
Good luck!
Why not using your own Servlet filter e.g.
public class YourFilter implements Filter {
...
#Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain filterChain) throws IOException, ServletException {
// HttpServletRequest httpReq = (HttpServletRequest) request;
// HttpServletResponse httpResp = (HttpServletResponse) response;
// HttpServletRequest httpReq = (HttpServletRequest) request;
// HttpServletResponse httpResp = (HttpServletResponse) response;
// ..... httpReq.getUserPrincipal();
// then set what you need using ThreadLocal and use it inside your resource class
// do not forget to call
filterChain.doFilter(request, response); // at the end of this method
}
The last step is to register your servlet filter. This is done using web app's web.xml
It will intercept your HTTP requests before the actual code inside jersey resource is called.
Here is my problem, I need to map a AJAX request using spring. Now, I know that I need these two guys:
HttpServletRequest, to get the message the client sent to me and parse it from JSON(most likely) to a Map and HttpServletResponse to put my message to the client.
What I do not know is the right(simple, concise) way to do that...
Here is a code sample from the springframework site:
/**
* Normal comments here
*
* ##org.springframework.web.servlet.handler.metadata.PathMap("/foo.cgi")
* ##org.springframework.web.servlet.handler.metadata.PathMap("/baz.cgi")
*/
public class FooController extends AbstractController {
private Cruncher cruncher;
public FooController(Cruncher cruncher) {
this.cruncher = cruncher;
}
protected ModelAndView handleRequestInternal (
HttpServletRequest request, HttpServletResponse response) throws Exception {
return new ModelAndView("test");
}
}
Which is nice. Except that, as far as I can see, I cannot map a URL for each method in that class as I would do with this kind of synchronous request:
#Controller
#RequestMapping("/test")
public class ControllerTest {
#RequestMapping(value = "/test.htm", method = RequestMethod.GET)
public void showSearchView(Model model) {...}
...
}
Can I do something that simple for AJAX requests?
Not sure where you found that first example on SpringSource! That is the old-bad(tm) way of doing it. I'm pretty sure AbstractController is even marked deprecated in Spring 3.
The second way works fine for mapping AJAX requests. If you really want to parse it all yourself, HttpServletRequest and HttpServletResponse are legal parameters for that handler method. However, Spring will happily do it for you: http://blog.springsource.com/2010/01/25/ajax-simplifications-in-spring-3-0/
(If you're stuck on an older version of Spring there are also 3rd party libraries for adding JSON mapping to handlers.)
This is the answer I found. I modified the method shown in my post and added a HttpServletRequest to the method arguments.
public void showSearchView(Model model, HttpServletRequest req, HttpServletRequest resp) {
if(req==null||resp==null)throw new RuntimeException("OLOLOLOLOL xD");
}
That's it. If anyone have a better answer or comments, I'd be glad to hear.