I am trying to set/request gZip in HTTP REQUEST HEADERS inside my Java CXF WS Client BUT for some reason its being IGNORED. I don't get back gZipped response. Here is how I am trying to set. I am using Apache CXF 2.3.2. What am I missing?
public class LoggerXML implements SOAPHandler<SOAPMessageContext> {
private String uniqueIdentifier;
private String sessionId;
public LoggerXML(String sessionId, String uniqueIdentifier) {
this.sessionId = sessionId;
this.uniqueIdentifier = uniqueIdentifier;
}
protected final void setLogStream(PrintStream ps) {
// out = ps;
}
public void init(Map c) {
uniqueIdentifier = "";
}
public Set<QName> getHeaders() {
return null;
}
public boolean handleMessage(SOAPMessageContext smc) {
Boolean outboundProperty = (Boolean)
smc.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
if(outboundProperty){
// Creating HTTP headers & setting gZip.
Map<String, List<String>> headers = (Map<String,
List<String>>) smc.get(MessageContext.HTTP_REQUEST_HEADERS);
if(headers == null){
//System.out.println("LoggerXML.handleMessage: headers = null");
headers = new HashMap<String, List<String>>();
}
// Add HTTP headers to the web service request
headers.put("Accept-Encoding", Collections.singletonList("gzip,deflate"));
//headers.put("Content-Encoding", Collections.singletonList("gzip"));
//headers.put("Accept-Encoding", Collections.singletonList("gzip"));
smc.put(MessageContext.HTTP_REQUEST_HEADERS, headers);
//smc.put("org.apache.cxf.transport.common.gzip.GZIPOutInterceptor.UseGzip","YES");
}
return true;
}
public boolean handleFault(SOAPMessageContext smc) {
return true;
}
// nothing to clean up
public void close(MessageContext messageContext) {
}
// nothing to clean up
public void destroy() {
}
// Other Methods....
}
This code works for me
// Get the underlying Client object from the proxy object of service interface
Client proxy = ClientProxy.getClient(stub);
// Creating HTTP headers
Map<String, List<String>> headers = new HashMap<String, List<String>>();
headers.put("Accept-Encoding", Arrays.asList("gzip"));
// Add HTTP headers to the web service request
proxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
Refer:http://singztechmusings.wordpress.com/2011/09/17/apache-cxf-how-to-add-custom-http-headers-to-a-web-service-request/
Related
I have a Spring boot SOAP services with cxf, and my Consumers are passing me SSO token in http header.. I am able to retrieve the SSO token using JAX-WS handler. I am saving that SSO token into handler class level variable, and after control going through various classes it reaches to a point where I have to make a request to another service and have to pass the same SSO token, but in my Connection class the SSO token value is NULL.
#Component
public class EndPointHandler implements SOAPHandler<SOAPMessageContext> {
private List<String> ssoToken;
private Map<String, List<String>> headers;
#Override
public boolean handleMessage(SOAPMessageContext context) {
Boolean isResponse = (Boolean) context.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (!isResponse) {
headers = ((Map<String, List<String>>) context.get(MessageContext.HTTP_REQUEST_HEADERS));
if (headers != null) {
if (!headers.get("SSOToken").get(0).isEmpty()) {
List<String> ssoToken = headers.get("SSOToken");
LOGGER.info(ssoToken.get(0));
this.ssoToken = ssoToken;
} else {
LOGGER.error("SSO Token value cannot be empty");
return false;
}
}
}
return true;
}
public void setSSOToken() {
headers.put("SSOToken", this.ssoToken);
}
}
In my Connection class I have to set this SSO token as a header and make a call to another service but SSO token value is NULL.
Connection Class:
#Component
public class ConnectionManager {
private static final Logger LOGGER = LoggerFactory.getLogger(ConnectionManager.class);
#Autowired
private EndPointHandler handler;
private void establishConnection(String uri) throws FileNetIntegrationException {
handler.ssoToken; // --> I need SSO token here but the value is NULL;
}
}
This is how I set the handler chain in my WebServiceConfig class:
#Bean
public Endpoint endpoint(Bus bus) {
EndpointImpl endpoint = new EndpointImpl(bus, changeServiceEndpoint);
WebService ws = AnnotationUtils.findAnnotation(endpoint.getImplementorClass(), WebService.class);
endpoint.setAddress("/" + ws.serviceName());
endpoint.publish();
SOAPBinding binding = (SOAPBinding) endpoint.getBinding();
ArrayList<Handler> handlerChain = new ArrayList<>();
handlerChain.add(new EndPointHandler());
binding.setHandlerChain(handlerChain);
return endpoint;
}
I think, I got a solution right after posting the last piece of code here when I noticed that I used new EndPointHandler() while adding it into handler chain.. I tried using Autowired it and it worked for me.
As far as I know, jax-ws context and spring-ws context don't intersect with each other. So this is not a solution but a workaround. As another workaround, you can use some singleton synchronizedMap, or use a jax-ws Handler to redirect requests to another endpoint with extended api.
Access HTTP headers of SOAP messages using JAX-WS handler
If you have configured SOAPHandler for your JAX-WS WebService, then you can access the HTTP headers and pass them on inside the SOAPBody as fields of the SOAPElement type, and vice versa. To do this you have to extend the messages POJOs with these fields annotated as XmlElement. Then you can access them from your WebService.
Note: If you have a dynamically generated WSDL schema based on Java classes, then it changes too. But anyway, the old requests and responses are accepted, because these fields are not required by default.
Example: UserService - the incoming message has one field of String type and outgoing message has one field of int type. Let's extend each of them with one ssoToken field of String type. We'll read this token from HTTP headers of incoming message and send it back in HTTP headers of outgoing message.
GetUserRequest.java:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType
#XmlRootElement(name = "getUserRequest")
public class GetUserRequest {
#XmlElement
protected String ssoToken;
#XmlElement(required = true)
protected String name;
// getters + setters + constructor
}
GetUserResponse.java:
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType
#XmlRootElement(name = "getUserResponse")
public class GetUserResponse {
#XmlElement
protected String ssoToken;
#XmlElement(required = true)
protected int age;
// getters + setters + constructor
}
UserServiceHandler.java
public class UserServiceHandler implements SOAPHandler<SOAPMessageContext> {
#Override
public boolean handleMessage(SOAPMessageContext soapMessageContext) {
Boolean isResponse =
(Boolean) soapMessageContext
.get(SOAPMessageContext.MESSAGE_OUTBOUND_PROPERTY);
if (!isResponse) {
// Request message
return processIncomingMessage(soapMessageContext);
} else {
// Response message
return processOutgoingMessage(soapMessageContext);
}
}
}
processIncomingMessage:
#SuppressWarnings("unchecked")
private boolean processIncomingMessage(SOAPMessageContext soapMessageContext) {
Map<String, List<String>> headers =
((Map<String, List<String>>) soapMessageContext
.get(MessageContext.HTTP_REQUEST_HEADERS));
if (headers == null || headers.isEmpty()) {
return false;
}
List<String> ssoTokens = headers.get("SSOToken");
if (ssoTokens == null || ssoTokens.size() != 1) {
return false;
}
String ssoToken = ssoTokens.get(0);
if (ssoToken == null || ssoToken.isEmpty()) {
return false;
}
try {
Iterator<Node> iterator =
soapMessageContext.getMessage().getSOAPBody().getChildElements();
while (iterator.hasNext()) {
Node element = iterator.next();
if (element.getNodeName().contains("getUserRequest")) {
((SOAPElement) element)
.addChildElement("ssoToken", element.getPrefix())
.setTextContent(ssoToken);
}
}
} catch (SOAPException e) {
e.printStackTrace();
return false;
}
return true;
}
processOutgoingMessage:
#SuppressWarnings("unchecked")
private boolean processOutgoingMessage(SOAPMessageContext soapMessageContext) {
Map<String, List<String>> headers =
((Map<String, List<String>>) soapMessageContext
.get(MessageContext.HTTP_RESPONSE_HEADERS));
if (headers == null || headers.isEmpty()) {
soapMessageContext
.put(MessageContext.HTTP_RESPONSE_HEADERS, new HashMap<>());
headers = ((Map<String, List<String>>) soapMessageContext
.get(MessageContext.HTTP_RESPONSE_HEADERS));
}
try {
Iterator<Node> iterator = soapMessageContext
.getMessage().getSOAPBody().getChildElements();
while (iterator.hasNext()) {
Node element = iterator.next();
if (element.getNodeName().contains("getUserResponse")) {
Iterator<Node> iteratorResponse =
((SOAPElement) element).getChildElements();
while (iteratorResponse.hasNext()) {
Node childElement = iteratorResponse.next();
if (childElement.getNodeName().contains("ssoToken")) {
String ssoToken = childElement.getTextContent();
headers.put("SSOToken",
Collections.singletonList(ssoToken));
element.removeChild(childElement);
}
}
}
}
} catch (SOAPException e) {
e.printStackTrace();
return false;
}
return true;
}
UserService.java
#WebService(endpointInterface = "com.example.UserPort",
serviceName = "UserService")
#HandlerChain(file="handler-chain.xml")
public class UserService implements UserPort {
public GetUserResponse getUser(GetUserRequest request) {
GetUserResponse response = new GetUserResponse();
response.setAge(23);
response.setSsoToken(request.getSsoToken());
return response;
}
}
Testing with SoapUI:
Request headers:
POST http://localhost:8080/ws/userService HTTP/1.1
Accept-Encoding: gzip,deflate
Content-Type: text/xml;charset=UTF-8
SOAPAction: ""
SSOToken: 6cd506ac-738a-43ca-aee8-d13b78180605
Content-Length: 296
Host: localhost:8080
Connection: Keep-Alive
User-Agent: Apache-HttpClient/4.1.1 (java 1.5)
Request message:
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:spr="http://example.com/jax-ws-sample">
<soapenv:Header/>
<soapenv:Body>
<spr:getUserRequest>
<spr:name>John</spr:name>
</spr:getUserRequest>
</soapenv:Body>
</soapenv:Envelope>
Response headers:
HTTP/1.1 200
SSOToken: 6cd506ac-738a-43ca-aee8-d13b78180605
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Date: Thu, 27 Aug 2020 15:54:33 GMT
Keep-Alive: timeout=20
Connection: keep-alive
Response message:
<S:Envelope
xmlns:S="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
<SOAP-ENV:Header/>
<S:Body>
<getUserResponse xmlns="http://example.com/jax-ws-sample">
<age>23</age>
</getUserResponse>
</S:Body>
</S:Envelope>
I have the following code to create a netty web server based on http server created in the netty's example. My buisness logic is the following.
public class HttpServerHandler extends SimpleChannelInboundHandler<Object> {
private final static Logger LOG = LogManager
.getLogger(HttpServerHandler.class);
private WorkflowService workflowService;
private HttpRequest request;
private final StringBuffer buff = new StringBuffer();
private API avalancheApi;
public HttpServerHandler(WorkflowService workflowService) {
this.workflowService = workflowService;
this.avalancheApi = new API(this.workflowService);
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
LOG.debug("channelActive");
LOG.debug(ctx.toString());
};
#Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.flush();
}
#Override
public void channelRead0(ChannelHandlerContext ctx, Object msg)
throws IOException {
avalancheApi.setContext(ctx);
if (msg instanceof HttpRequest) {
HttpRequest request = this.request = (HttpRequest) msg;
if (HttpHeaders.is100ContinueExpected(request)) {
send100Continue(ctx);
}
String command = getCommand(request);
LOG.debug(command);
Map<String, List<String>> parameters = getParameters(request);
LOG.debug(parameters);
switch (command) {
case "/login":
ctx = avalancheApi.login(parameters);
break;
case "/test":
ctx = avalancheApi.test();
break;
default:
break;
}
}
if (msg instanceof LastHttpContent) {
LOG.debug("msg is of LastHttpContent");
}
if (!HttpHeaders.isKeepAlive(request)) {
// If keep-alive is off, close the connection once the content is
// fully written.
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(
ChannelFutureListener.CLOSE);
}
}
public class API {
private static final Logger LOG = LogManager.getLogger(API.class);
private ChannelHandlerContext ctx;
private HttpResponse response;
private WorkflowService workflowService;
public API(WorkflowService workflowService) {
this.workflowService = workflowService;
this.ctx = null;
}
public void setContext(ChannelHandlerContext ctx) {
this.ctx = ctx;
}
public ChannelHandlerContext login(Map<String, List<String>> parameters) {
boolean success;
String username = getUsername(parameters);
String password = getPassword(parameters);
User user = null;
user = workflowService.login(username, password);
success = validateLogin(user);
this.response = writeLoginResponse(success);
this.ctx.write(this.response);
writeLoginContext(success, response);
return this.ctx;
}
private void writeLoginContext(boolean success, HttpResponse response) {
JsonObject jsonResponseMessage = new JsonObject();
jsonResponseMessage.addProperty("result", success);
LOG.debug(jsonResponseMessage.toString());
this.ctx.write(Unpooled.copiedBuffer(jsonResponseMessage.toString(),
CharsetUtil.UTF_8));
this.response.headers().set(HttpHeaders.Names.CONTENT_LENGTH,
jsonResponseMessage.toString().length());
}
private HttpResponse writeLoginResponse(boolean success) {
if (success)
return createSuccessfullLoginResponse();
else
return createLoginFailureResponse();
}
private HttpResponse createLoginFailureResponse() {
return Response.loginFailureResponse();
}
private HttpResponse createSuccessfullLoginResponse() {
return Response.loginSuccessResponse();
}
}
Response class is only creating the response and the content_type which is of application/json. Content Length is set in the API class. Using python client with requests, results in the request made in http://localhost/login?username=name&password=pass works only once. The second time everything works, but it doesn't finish processing the request and send the response object. Api calls get executed normally, and I also get the message of LastHttpContext message getting print. The problem sometimes happens with browser too. Am I missing something? Maybe the content data and the content length doesn't match? Could it be that when making requests from python client, the content of the previous context isn't flushed and the content_length value of the header and content length of the context doesn't match?
Just wild guess
this.response.headers().set(HttpHeaders.Names.CONTENT_LENGTH,
jsonResponseMessage.toString().length());
Instead, shouldn't you be doing jsonResponseMessage.toString().getBytes().length ?? Sometimes, one character is not just one byte.
My guess is that you have overwritten the context in your API class, and as a result, are writing the response to the wrong context. Is your HttpServerHandler marked with #Shareable?
i´m implementing a Restful service using Jax-RS 2.0 (Resteasy 3.0.7.Final) and share the interface between client and service.
The return value is void because ClientResponse is deprecated since RestEasy introduced JAX-RS 2.0 in version 3+.
To return the location of the new created object i inject the response, using the #Context annotation, and add the Content-Location header.
For example:
Shared Interface:
#Path("/")
#Consumes("application/xml")
#Produces("application/xml")
interface Resource {
#Path("createSomething")
void createSomething(AnyObject object);
...
}
Implementation class (The Service):
class ResourceImpl {
...
#Context org.jboss.resteasy.spi.HttpResponse response;
...
#Override
void createSomething(AnyObject object) throws AnyException {
String id = service.create(object);
response.getOutputHeaders().putSingle("Content-Location",
"/createSomething/" + id);
response.setStatus(Response.Status.CREATED.getStatusCode());
}
}
The client (build with the Resteasy Proxy Framework):
...
ResteasyClient client = new ResteasyClientBuilder().build();
ResteasyWebTarget target = client.target(baseUrl);
Resource resource = (Resource) target.proxy(Resource.class);
resource.createSomething(anyObject);
...
How can i retrieve Header information (and others, like Atom Links) which has been injected by the service?
Is it reasonable to use client side Filters and Interceptors?
Thank You
The best solution i found was to use a Filter to process the incoming response header.
public class HeaderFilter implements ClientResponseFilter {
private Map<String, String> headers = new HashMap<>();
private List<String> headerFilter = new ArrayList<>();
public final void addHeaderFilter(final String header) {
headerFilter.add(header);
}
public final void removeHeaderFilter(final String header) {
headerFilter.remove(header);
}
public final String getHeader(final String header) {
return headers.get(header);
}
#Override
public final void filter(final ClientRequestContext requestContext,
final ClientResponseContext responseContext)
throws IOException {
headers = new HashMap<>();
for (String headerToLookFor : headerFilter) {
String header = responseContext.getHeaderString(headerToLookFor);
if (header != null) {
headers.put(headerToLookFor, header);
} else {
...
}
}
}
}
I am using Jersey client to connect to an SSE stream. The server requires that I add a header to the http request for authorization, but I can't figure out how to add the header.
Here is my code:
Client client = ClientBuilder.newBuilder().register(SseFeature.class).build();
WebTarget target = client.target(baseurl + "/v1/devices/events/");
eventSource = EventSource.target(target).build();
eventSource.register(getEventListener());
eventSource.open();
Here is an example of the header I need to add:
Authorization: Bearer 38bb7b318cc6898c80317decb34525844bc9db55
It would be something like this for Basic Authentication:
Client client = ClientBuilder.newClient();
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basicBuilder().build();
client.register(feature);
client.register(SseFeature.class);
WebTarget target = client.target(baseurl + "/v1/devices/events/")
.property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_USERNAME, "...")
.property(HttpAuthenticationFeature.HTTP_AUTHENTICATION_BASIC_PASSWORD, "...");
...
You already get the password encoded by Jersey.
And if it is a token:
Client client = ClientBuilder.newClient();
WebTarget target = client.target(baseurl + "/v1/devices/events/")
.request("...")
.header(HttpHeaders.AUTHORIZATION, "Bearer " + "... encoded token ...");
Hope it helps!
In case someone would want to add the bearer token header at the Client entity level itself, rather than at the Request entity level (in my case I had a factory method for returning preconfigured Client entities, so I had no way of adding the authorization header within the factory method, as .header(...) becomes available only after you go through the ClientBuilder.newBuilder().register(...).build().target(...).request(...) call chain, as of Jersey 2.x):
// client is a javax.ws.rs.client.Client entity
Feature feature = OAuth2ClientSupport.feature("YOUR_BEARER_TOKEN");
client.register(feature);
// now you can use client.target(...).request(...).post(...), without calling .header(...) after .request(...)
Unfortunately (as you may have guessed) this requires a new dependency: org.glassfish.jersey.security:oauth2-client
<dependency>
<groupId>org.glassfish.jersey.security</groupId>
<artifactId>oauth2-client</artifactId>
<version>2.15</version>
</dependency>
// Using SSL + Header Key
uri = UriBuilder.fromUri(sslUrl).port(sslServerPort).build();
sslConfig = SslConfigurator.newInstance().trustStoreFile(trustStoreFile).trustStorePassword(trustStorePassword);
sslContext = sslConfig.createSSLContext();
client = ClientBuilder.newBuilder().sslContext(sslContext).build();
target = client.target(uri).path(path);
Entity<?> entity = Entity.entity(Object, MediaType.APPLICATION_JSON);
response = target.request().header("key","value").post(entity);
// Using UserName & Password + Header Key
uri = UriBuilder.fromUri(url).port(serverPort).build();
basicAuth = HttpAuthenticationFeature.basic(username, userPassword);
client = ClientBuilder.newBuilder().register(basicAuth).build();
target = client.target(uri).path(path);
Entity<?> entity = Entity.entity(Object, MediaType.APPLICATION_JSON);
response = target.request().header("key","value").post(entity);
// Using only Header Key
uri = UriBuilder.fromUri(url).port(serverPort).build();
client = ClientBuilder.newBuilder().build();
target = client.target(uri).path(path);
Entity<?> entity = Entity.entity(Object, MediaType.APPLICATION_JSON);
response = target.request().header("key","value").post(entity);
Hope this helps you with your problem.
Here is the complete examples
ClientConfig clientConfig = new ClientConfig();
Client client = ClientBuilder.newClient(clientConfig);
WebTarget webTarget = client.target("http://localhost:8080/MyApp/customer/");
Invocation.Builder invocationBuilder =
webTarget.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, "your
secret key");
response = invocationBuilder.get();
output = response.readEntity(String.class);
Dependency for jersey client
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.25.1</version>
</dependency>
Try this:
Invocation.Builder invocationBuilder = target.request(MediaType.APPLICATION_JSON).header(HttpHeaders.AUTHORIZATION, "Bearer38bb7b318cc6898c80317decb34525844bc9db55");
I realize this question is a year old but since there are not a lot to be found on that subject, I'll share my solution.
Based on suggested OAuth2Feature, I came up with this solution:
Create a custom feature. Feature will reference a custom filter
Create a custom filter of priority HEADER_DECORATOR
Create a HeaderProvider interface. Provider will be passed to the filter
Register the WebClient with the custom feature
Header provider interface
#FunctionalInterface
public interface ISseHeaderProvider {
Map<String, String> getHeaders();
}
Custom feature
public class SseHeaderSupportFeature implements Feature {
private final SseHeaderSupportFilter filter;
public SseHeaderSupportFeature(ISseHeaderProvider provider) {
this.filter = new SseHeaderSupportFilter(provider);
}
#Override
public boolean configure(FeatureContext context) {
context.register(filter);
return true;
}
}
Custom filter
#Priority(Priorities.HEADER_DECORATOR)
public class SseHeaderSupportFilter implements ClientRequestFilter {
private final ISseHeaderProvider provider;
public SseHeaderSupportFilter(#NotNull ISseHeaderProvider provider) {
this.provider = provider;
}
#Override
public void filter(ClientRequestContext request) throws IOException {
provider.getHeaders().forEach((k, v) -> request.getHeaders().add(k, v));
}
}
Usage
ISseHeaderProvider provider = () -> MapBuilder.<String, String>builder().add("Authorization", "Bearer ...").build();
Client client = ClientBuilder.newBuilder()
.register(SseFeature.class)
.register(new SseHeaderSupportFeature(provider))
.build();
WebTarget target = client.target(UriBuilder.fromPath(getUrl()));
//EventSource eventSource = ....
This solution is generic and allows you to easily add an Authorization header without having to add another dependency.
Following answer is useful:
Server Sent Event Client with additional Cookie
It use a customized WebTarget to add cookie and the same way on header also work.
public class AuthorizationHeaderWebTarget implements WebTarget {
private WebTarget base;
private String token;
public AuthorizationHeaderWebTarget(WebTarget base, String token) {
this.base = base;
this.token = token;
}
// Inject that cookie whenever someone requests a Builder (like EventSource does):
public Invocation.Builder request() {
return base.request().header(HttpHeaders.AUTHORIZATION, token);
}
public Invocation.Builder request(String... paramArrayOfString) {
return base.request(paramArrayOfString).header(HttpHeaders.AUTHORIZATION, token);
}
public Invocation.Builder request(MediaType... paramArrayOfMediaType) {
return base.request(paramArrayOfMediaType).header(HttpHeaders.AUTHORIZATION, token);
}
public Configuration getConfiguration() {
return base.getConfiguration();
}
//All other methods from WebTarget are delegated as-is:
public URI getUri() {
return base.getUri();
}
public UriBuilder getUriBuilder() {
return base.getUriBuilder();
}
public WebTarget path(String paramString) {
return base.path(paramString);
}
public WebTarget matrixParam(String paramString, Object... paramArrayOfObject) {
return base.matrixParam(paramString, paramArrayOfObject);
}
public WebTarget property(String paramString, Object paramObject) {
return base.property(paramString, paramObject);
}
public WebTarget queryParam(String paramString, Object... paramArrayOfObject) {
return base.queryParam(paramString, paramArrayOfObject);
}
public WebTarget register(Class<?> paramClass, Class<?>... paramArrayOfClass) {
return base.register(paramClass, paramArrayOfClass);
}
public WebTarget register(Class<?> paramClass, int paramInt) {
return base.register(paramClass, paramInt);
}
public WebTarget register(Class<?> paramClass, Map<Class<?>, Integer> paramMap) {
return base.register(paramClass, paramMap);
}
public WebTarget register(Class<?> paramClass) {
return base.register(paramClass);
}
public WebTarget register(Object paramObject, Class<?>... paramArrayOfClass) {
return base.register(paramObject, paramArrayOfClass);
}
public WebTarget register(Object paramObject, int paramInt) {
return base.register(paramObject, paramInt);
}
public WebTarget register(Object paramObject, Map<Class<?>, Integer> paramMap) {
return base.register(paramObject, paramMap);
}
public WebTarget register(Object paramObject) {
return base.register(paramObject);
}
public WebTarget resolveTemplate(String paramString, Object paramObject) {
return base.resolveTemplate(paramString, paramObject);
}
public WebTarget resolveTemplate(String paramString, Object paramObject, boolean paramBoolean) {
return base.resolveTemplate(paramString, paramObject, paramBoolean);
}
public WebTarget resolveTemplateFromEncoded(String paramString, Object paramObject) {
return base.resolveTemplateFromEncoded(paramString, paramObject);
}
public WebTarget resolveTemplates(Map<String, Object> paramMap) {
return base.resolveTemplates(paramMap);
}
public WebTarget resolveTemplates(Map<String, Object> paramMap, boolean paramBoolean) {
return base.resolveTemplates(paramMap, paramBoolean);
}
public WebTarget resolveTemplatesFromEncoded(Map<String, Object> paramMap) {
return base.resolveTemplatesFromEncoded(paramMap);
}
}
Following is the code to use it:
EventSource eventSource = new EventSource(new AuthorizationHeaderWebTarget(target, token));
eventSource.register(new EventListener() {
public void onEvent(final InboundEvent inboundEvent) {
//...
}
});
If you use jercy client using header in websource
Client client=Client.create();
WebResource webresource=client.resource(urlLink);
ClientResponse clientResponse=webresource.header("authorization", accessToken)
.accept(MediaType.APPLICATION_JSON).get(ClientResponse.class);
Overriding getHeaders() works to add customs headers if necessary to the requests.
But what if X header is always needed to be set? for example an static auth token.
JsonObjectRequest req = new JsonObjectRequest(URL, new JSONObject(params),
new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
setFollowButton(item);
}
}, null){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "Token XXXXXXXXXXXX");
return headers;
}
};
Application.getInstance().addToRequestQueue(req);
Can be the header added to the request sent to the addToRequestQueue method instead overwriting it every time I write a request?
I believe the best way is extend the HttpStack sub-class which you choose to use, then intercepting the performRequest() method, put your global headers inside it.
public class MyHurlStack extends HurlStack {
#Override
public HttpResponse performRequest(
Request<?> request, Map<String, String> additionalHeaders)
throws IOException, AuthFailureError {
Map<String, String> headers = request.getHeaders();
// put your global headers
headers.put("Via", "netroid");
headers.put("Accept-Charset", "UTF-8");
headers.put("Origin", "http://netroid.cn/");
return super.performRequest(request, additionalHeaders);
}
}
public class MyHttpClientStack extends HttpClientStack {
public MyHttpClientStack(HttpClient client) {
super(client);
}
#Override
protected void onPrepareRequest(HttpUriRequest request) throws IOException {
// put your global headers
request.setHeader("Via", "netroid");
request.setHeader("Accept-Charset", "UTF-8");
request.setHeader("Origin", "http://netroid.cn/");
super.onPrepareRequest(request);
}
}
when RequestQueue initializing, use the customize HttpStack instead of.
if (stack == null) {
if (Build.VERSION.SDK_INT >= 9) {
stack = new HurlStack();
} else {
stack = new MyHttpClientStack(AndroidHttpClient.newInstance(userAgent));
}
}
Network network = new BasicNetwork(stack);
After a long search on how to add custom headers on each request with the volley android library,
I used HurlStack as bellow, hope it helps someone.
private static class MyHurl extends HurlStack{
#Override
public HttpResponse executeRequest(Request<?> request, Map<String, String> additionalHeaders){
Map<String, String> headers = new HashMap<>(additionalHeaders);
headers.put("authKey","myauthkey");
try {
return super.executeRequest(request, headers);
} catch (IOException e) {
} catch (AuthFailureError authFailureError) {
}
return null;
}
}