How to change permanently the user-agent on windows phone? - windows-phone

I want to change the user-agent of my webbrowser control. I can do this:
webbrowserTest.Navigate(new Uri("http://mywebsite.com"), null, "User-Agent: myuseragent");
The problem is that the user agent will only be valid for one request and not for subrequest or redirections. How to change permanently this user agent ?

since it's sealed class I don't think there is some way to intercepting HttpRequest creation and I would generally avoid such think since you can have other requests later on that won't need UserAgent/other header. Easiest thing to do here will probably be to create extension method in separate static class, e.g.:
public static class WebBrowserExtensions
{
public static void NavigateWithUserAgent(this WebBrowser webBrowser, Uri uri)
{
webBrowser.Navigate(uri, null, "User-Agent: myuseragent");
}
}
And then just call:
new WebBrowser().NavigateWithUserAgent(new Uri("http://mywebsite.com"));
Hope this helps.

Related

MobileFirst 8: get client data ( IP address, request data ) in UserAuthenticationSecurityCheck

I'm trying to get some client data inside the UserAuthenticationSecurityCheck.validateCredentials method.
The IP Address is the most important for it.
In the other adapters, I'm using the HttpServletRequest:
#Context
protected HttpServletRequest request;
But this request object is always null in the UserAuthenticationSecurityCheck.
How can I get client data (IP Address or the headers) in this class?
You cannot inject the HttpServletRequest into a security check object(by design - not a bug). Once the user is authenticated, then you can make another Adapter Call, from where you can get the desired details. Unfortunately this is not documented anywhere (not to my knowledge at least).
I had a similar issue with AdapterAPI class as described here.
You can get request in security adapter but not from #Context.
Just override authorize method:
#Override
public void authorize(Set<String> scope, Map<String, Object> credentials, HttpServletRequest request, AuthorizationResponse response) {
//TODO use request object
super.authorize(scope, credentials, request, response);
}

Receiving gzip Content-Encoding with dotNetRDF

How do I tell dotNetRDF to request and accept data from a remote triplestore where the response is encoded using gzip?
Looking at the source code for the LoadGraph method of SparqlHttpProtocolConnector, it doesn't appear to me to have a mechanism for setting the Accept-Encoding header, nor am I seeing any logic that would process a Content-Encoding header.
I tried modifying LoadGraph to set Accept-Encoding, and the content then comes back with the right Content-Type and Content-Encoding, but the line of code that determines how to handle the response is
IRdfReader parser = MimeTypesHelper.GetParser(response.ContentType);
and GetParser doesn't have any logic that considers the Content-Encoding.
However, it seems like the pieces are present: there's certainly infrastructure in place to process a gzipped file.
Is there another way to do this that I'm missing, or would this be a new feature request?
Thanks.
You can extend SPARQLHttpProtocolConnector and then override the ApplyCustomRequestOptions method to apply the Accept-Encoding header.
Although the MimeTypesHelper does not discriminate on the Content-Encoding header of the response, you can instead use the HttpWebRequest.AutomaticDecompression Property to enable automatic decompression of the response stream. Again, this can be set in the ApplyCustomRequestOptions method.
So your extension class would be something like this:
public class CompressedSparqlHttpProtocolConnector : SparqlHttpProtocolConnector
{
// Define appropriate constructors with the parameters you need e.g.
public CompressedSparqlHttpProtocolConnector(Uri serviceUri)
: base(serviceUri) { }
protected override ApplyCustomRequestOptions(HttpWebRequest request)
{
// Request GZip encoded response, allow fallback to identity encoding
request.Headers[HttpRequestHeader.ContentEncoding] = "gzip;q=1.0, identity;q=0.5"
// Enable automatic decompression of the response
request.AutomaticDecompression = DecompressionMethods.GZip;
}
}

HttpContext.Current.Request is not available in RegisterGlobalFilters

I am trying to add RequireHttpsAttribute attribute to MVC filters collection to push web site to HTTPS when it is deployed on prod server. The problem is with HttpContext.Current.Request.IsLocal line, the Request object is not available yet. Then how to check is site running localy or on prod server in RegisterGlobalFilters?
public static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
if (!HttpContext.Current.Request.IsLocal) //Exception here!!!
{
filters.Add(new RequireHttpsAttribute());
}
}
In this method you are to register the filters that will do the checking when the request comes in. This method will only get called once each time the application is started. So here you need to do something along the lines of:
filters.Add(new MyAuthorizeAttribute());
With MyAuthorizeAttribute being something along the lines of:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
If(!httpContext.Request.IsLocal)
{
**//Check for HTTPS and return false if need be**
}
}
Of course it does not need to be an AuthorizeAttribute.
EDIT
As I said before this method is called only once at the start of the application so there is no request for you to check in here. Here you can only apply filters that will be called every time a request is received. It is inside those filters that you can check request specific properties.
If you insist on using the RequireHttpsAttribute, than you either have to apply it to all methods regardless of whether the request is local or not or you have to extend RequireHttpsAttribute and override HandleNonHttpsRequest to handle local requests.

Content-Type case sensitivity in RESTEasy 3

I am developing a RestEasy client to connect to a 3rd party REST service which has defined its own custom media types. A made up example is
application/vnd.abc.thirdPartyThing-v1+json
Note the uppercase P in thirdParty.
I am using RESTEasy 3.0.11 for my client implementation. At the point where I make a POST call to the service my code looks like
Response response = target.request()
.post(Entity.<ThirdPartyThing>entity(
thing,
"application/vnd.abc.thirdPartyThing-v1+json"));
but RESTEasy sends to the server
Content-Type: application/vnd.abc.thirdpartything-v1+json
This is due to RESTEasy's MediaTypeHeaderDelegate class's toString() method, which lowercases the type and subtype MediaTypeHeaderDelegate. This should be correct, or at least unimportant, as RFC-1341 states that Content-Type values are case-insensitive - RFC-1341
Unfortunately the 3rd party service is checking the Content-Type in a case sensitive manner and so returning a 415 UNSUPPORTED MEDIA TYPE error. I've tested using curl which doesn't alter the content-type value and confirmed that it's a case issue. application/vnd.abc.thirdPartyThing-v1+json works, application/vnd.abc.thirdpartything-v1+json does not.
I'm in the process of raising a ticket, but in the meantime is there any way to override RESTEasy's default behaviour and send Content-Type headers without lowercasing the value?
Thanks for reading.
I could reproduce this behavior with RESTeasy 3.0.6.Final and would not expect it. Maybe you could check their JIRA if this has already been discussed or open an issue. I once had problems on the server side because a 2.x version of RESTeasy was checking the charset attribute of the Content-Type header case-sensitive. This was also changed.
You could solve this problem by a really ugly workaround: Overwrite the header again in a ClientRequestFilter.
public class ContentTypeFilter implements ClientRequestFilter {
private Map<String, String> contentTypes;
public ContentTypeFilter() {
contentTypes = new HashMap<>();
contentTypes.put("text/foo", "text/Foo");
}
#Override
public void filter(ClientRequestContext requestContext) throws IOException {
String contentType = requestContext.getHeaderString("Content-Type");
if (contentTypes.containsKey(contentType)) {
requestContext.getHeaders().putSingle("Content-Type", contentTypes.get(contentType));
}
}
}
Don't forget to register this Filter:
Client client = ClientBuilder.newClient().register(ContentTypeFilter.class);

Apache Http Client Put Request Error

I'm trying to upload a file using the Apache Http Client's PUT method. The code is as below;
def putFile(resource: String, file: File): (Int, String) = {
val httpClient = new DefaultHttpClient(connManager)
httpClient.getCredentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(un, pw))
val url = address + "/" + resource
val put = new HttpPut(url)
put.setEntity(new FileEntity(file, "application/xml"))
executeHttp(httpClient, put) match {
case Success(answer) => (answer.getStatusLine.getStatusCode, "Successfully uploaded file")
case Failure(e) => {
e.printStackTrace()
(-1, e.getMessage)
}
}
}
When I tried running the method, I get to see the following error:
org.apache.http.NoHttpResponseException: The target server failed to respond
at org.apache.http.impl.conn.DefaultResponseParser.parseHead(DefaultResponseParser.java:101)
at org.apache.http.impl.io.AbstractMessageParser.parse(AbstractMessageParser.java:252)
at org.apache.http.impl.AbstractHttpClientConnection.receiveResponseHeader(AbstractHttpClientConnection.java:281)
at org.apache.http.impl.conn.DefaultClientConnection.receiveResponseHeader(DefaultClientConnection.java:247)
at org.apache.http.impl.conn.AbstractClientConnAdapter.receiveResponseHeader(AbstractClientConnAdapter.java:219)
at org.apache.http.protocol.HttpRequestExecutor.doReceiveResponse(HttpRequestExecutor.java:298)
at org.apache.http.protocol.HttpRequestExecutor.execute(HttpRequestExecutor.java:125)
at org.apache.http.impl.client.DefaultRequestDirector.tryExecute(DefaultRequestDirector.java:633)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:454)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)
I do not know what has gone wrong? I'm able to do GET requests, but PUT seems not to work! Any clues as to where I should look for?
Look on the server. If GET Works, but PUT does not, then you have to figure out the receiving end.
Also, you may want to write a simple HTML File that has a form with PUT Method in it to rule out your Java Part.
As a sidenode: Its technically possible that something in between stops the request from going through or the response reaching you. Best setup a dummy HTTP Server to do the testing against.
Maybe its also a timeout issue, so the server takes to long to process your PUT.
The connection you are trying to use is a stale connection and therefore the request is failing.
But why are you only seeing an error for the PUT request and you are not seeing it for the GET request?
If you check the DefaultHttpRequestRetryHandler class you will see that by default HttpClient attempts to automatically recover from I/O exceptions. The default auto-recovery mechanism is limited to just a few exceptions that are known to be safe.
HttpClient will make no attempt to recover from any logical or HTTP protocol errors (those derived from HttpException class).
HttpClient will automatically retry those methods that are assumed to be idempotent. Your GET request, but not your PUT request!!
HttpClient will automatically retry those methods that fail with a transport exception while the HTTP request is still being transmitted to the target server (i.e. the request has not been fully transmitted to the server).
This is why you don't notice any error with your GET request, because the retry mechanism handles it.
You should define a CustomHttpRequestRetryHandler extending the DefaultHttpRequestRetryHandler. Something like this:
public class CustomHttpRequestRetryHandler extends DefaultHttpRequestRetryHandler {
#Override
public boolean retryRequest(IOException exception, int executionCount, HttpContext context) {
if(exception instanceof NoHttpResponseException) {
return true;
}
return super.retryRequest(exception, executionCount, context);
}
}
Then just assign your CustomHttpRequestRetryHandler
final HttpClientBuilder httpClientBuilder = HttpClients.custom();
httpClientBuilder.setRetryHandler(new CustomHttpRequestRetryHandler());
And that's it, now your PUT request is handled by your new RetryHandler (like the GET was by the default one)