How can i add authentication header in asnetworkimagenode url request? - ios

I'm using AsyncDisplaykit in my swift application and ASNetworkImageNode as my imageview in collectionNode. I can load any external url with great performance but for my application I need to communicate with our api which requires authentication header to be sent on each GET request. How can i add authentication header in asnetworkimagenode url request or write an extension or any other workaround to achieve this?

I searched the library files and found that there is a setSharedImageManagerWith(_:URLSessionConfiguration?) in PINRemoteImageManager. One can add additional header in session configuration. So in swift 3 the code can be added in appdelegate didFinishLaunchingWithOptions as:
let config = URLSessionConfiguration.ephemeral
config.httpAdditionalHeaders = [
"clientid": "yourAdditionalHeader",
"clientkey": "yourAdditionalHeader"
] as [AnyHashable:Any]
ASPINRemoteImageDownloader.setSharedImageManagerWith(config)
Now setting the url in AsNetworkImageNode will send the url request with additional headers added to the request. This has solved my issue.
The doc of PINRemoteImageManager reads
"Sets the shared instance of PINRemoteImageManager to an instance with the supplied configuration. If configuration is nil, [NSURLSessionConfiguration ephemeralSessionConfiguration] is used. You specify a custom configuration if you need to configure timeout values, cookie policies, additional HTTP headers, etc. This method should not be used if the shared instance has already been created."
So the similar code can be used to configure timeout values, cookie policy and of course additional http headers. Hope this will help someone.

Related

Signing http request with Akka HTTP client for oauth1

I'm trying to find a way for executing http requests with OAuth authorization. Basically I already have all required secrets/tokens
For sending such request should be signed in a rather tricky way described here: https://oauth1.wp-api.org/docs/basics/Signing.html
Are there any libraries/examples for this suitable for Akka HTTP client's API?
Since I didn't find any solution for that, I've implemented method for GET-requests:
https://gist.github.com/Blackmorse/cdb5e13d749e7902ad47d5a168dd23ca
Usage:
E.g. you want request data from s"$URL/$API_ENDPOINT?param1=value1&param2=value2".
To construct the Akks's akka.http.scaladsl.model.HttpRequest object:
val request = create(Map("param1" -> "value1", "param2" -> "value2"))
And use it:
Source.single((request, someData)).via(Http().cachedHostConnectionPoolHttps[T](URL))

Check validity of cached HTTP response

Using the URLSession family of classes, is there a way to check the validity of a response? Specifically, I have an HTTP response whose Cache-Control header specifies no-cache, so that any cached response will have to be submitted for validation before it can be used. I can retrieve the CachedURLResponse object from URLCache.shared, but none of URLSession, URLCache, or CachedURLResponse seem to have any methods for determining whether such a cached response is still valid. Such methods are also absent from URLSessionDelegate and URLSessionTaskDelegate.
Is there any way to do this other than initiating the actual validation request myself? Presumably this is done somewhere in the URLSession stack (although I'm not sure of this), but it looks as if this functionality may just not be exposed by the public API.
The question is why do you need to check the validity. If you want only to check the validity you may use a probably uncommon method by using URLProtocol and writing a custom NSURLProtocolClient. The client has only empty methods except:
func urlProtocol(_ protocol: URLProtocol, cachedResponseIsValid cachedResponse: CachedURLResponse) {
// Cached response is valid. Store this information in a appropriate way.
protocol.stopLoading()
}
Now, you create a protocol with that client
let myClient = ...
let protocol = NSURLProtocol(request, cachedResponse, client: myClient)
protocol.startLoading()
protocol.stopLoading() // Stop, if urlProtocol(_: cachedResponseIsValid:) was not called
As far as I know, the caching of an HTTP response is handled automatically. (Just to be sure, I tried it again just before answering this question).
The default caching policy on a URLRequest is useProtocolCachePolicy. So, on all the subsequent requests to that url, the HTTP headers will contain the If-None-Match key, with the latest Etag as its value.
If this is not working for you automatically, make sure that the server is sending the Etag header in its response. Also, that the server acknowledges the If-None-Match header on all the requests.
TL;DR
CHECK:
That you get the Cache-Control and the Etag header in your
responses from the server.
That the server receives an If-None-Match header with the
correct Etag value, in all the subsequent requests.
That the server is actually configured to handle the cached
responses (As in, it responds to the If-None-Match header
correctly).
References:
https://developer.apple.com/documentation/foundation/nsurlrequest.cachepolicy
https://devcenter.heroku.com/articles/ios-network-caching-http-headers

How to disable Rails 5 "X-Request-Id" header

On Rails 5, all requests includes an unique identifier accessible on application and displayed on HTTP response headers, called "X-Request-Id".
This identifier is very useful for debugging and logging, but I'm having trouble with this in a very old web client.
I tried to clear the header but it did not work.
response.headers['X-Request-Id'] = nil
How can I remove this information from headers?
You can disable it by adding this line in your config/application.rb file:
config.middleware.delete ActionDispatch::RequestId
You can disable this header information, setting by nil this request attribute.
request.request_id = nil

What should I do to prevent a 401 Unauthorised when using the Swagger Type Provider?

When attempting to perform an HTTP post via Swagger (using the Swagger Type Provider) I get a 401 Unauthorized.
I suspect the answer to this might be UseDefaultCredentials which isn't exposed when inheriting from the SwaggerProvider.Internal.ProvidedSwaggerBaseType. So I was thinking that an upcast :> might help but posts I've seen elsewhere indicate naïveté.
Also, updating the config for fsi.exe to include the following proved wishful:
<system.net>
<defaultProxy enabled="true" useDefaultCredentials="true">
<proxy usesystemdefault="True" />
</defaultProxy>
</system.net>
Might anyone have a simple answer?
Thanks
Schema access
SwaggerProvider assumes that Swagger schema is easy-accessible and can be downloaded using simple Http request without authentication
type PetStore = SwaggerProvider<"http://petstore.swagger.io/v2/swagger.json">
user also can add any HTTP header to schema-request like this
type PetStore = SwaggerProvider<"http://petstore.swagger.io/v2/swagger.json", "Content-Type=application/json">
It can be Authorization: Basic QWxhZGRpbjpPcGVuU2VzYW1l header, but this literal string will be hard-coded in source code.
If schema-request requires more complex authentication, will be easier to download it and put it near source code
[<Literal>]
let schemaPath = __SOURCE_DIRECTORY__ + "/PetStore.Swagger.json"
type PetStore = SwaggerProvider<schemaPath>
Requests control
When schema are in place you have a full control over all HTTP request to the server using CustomizeHttpRequest parameter in provided type.
For example, if you want to use default credentials:
let store =
PetStore(
CustomizeHttpRequest=
fun (req:System.Net.HttpWebRequest) ->
req.UseDefaultCredentials <- true
req)
You are free to modify web request as you need:
Use default credentials
Specify runtime Credentials
Add headers to HTTP request
Add cookies to HTTP request
Break request ;) and etc.
CustomizeHttpRequest will be called in the run-time for each request, after SwaggerProvider built it and before call to the server. So you can change anything you want.

Does Alamofire store the cookies automatically?

I'm new to Alamofire so I'm sorry if this it's a noob question: this framework stores the cookies automatically?
This is because I have a simple request like this:
Alamofire.request(.POST, loginURL, parameters: ["fb_id": fbId, "fb_access_token": fbToken])
.responseJSON { response in
//print(response.request) // original URL request
//print(response.response) // URL response
//print(response.data) // server data
//print(response.result) // result of response serialization
if let JSON = response.result.value {
print("loginURL - JSON: \(JSON)")
}
}
this request response with a cookie session that I need to do other requests for security reason; the strange thing is that like magic I already can do the other requests after this first POST without read manually the cookie and store it. I'm sure the other requests need the cookie session because they fail on postman for example but not here.
It's just a feature? Because I can't find anything on that also on the official GitHub page.
Yes! Alamofire is basically a wrapper around NSURLSession. Its manager uses a default NSURLSessionConfiguration by calling defaultSessionConfiguration().
As its github page says under Advanced Usage section:
Alamofire is built on NSURLSession and the Foundation URL Loading System. To make the most of this framework, it is recommended that you be familiar with the concepts and capabilities of the underlying networking stack.
And under Manager section:
Top-level convenience methods like Alamofire.request use a shared instance of Alamofire.Manager, which is configured with the default NSURLSessionConfiguration.
And the NSURLSessionConfiguration reference for defaultSessionConfiguration() says:
The default session configuration uses a persistent disk-based cache (except when the result is downloaded to a file) and stores credentials in the user’s keychain. It also stores cookies (by default) in the same shared cookie store as the NSURLConnection and NSURLDownload classes.
For those who use Moya and want to disable stored cookies
(fixing the X-CSRF-Token request header is missing)
Very basic example:
public final class DisableCookiePlugin: PluginType {
public init() {
}
public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
var mutableRequest = request
mutableRequest.httpShouldHandleCookies = false
return mutableRequest
}
}
And then use it
MoyaProvider<Api>(
plugins: [
//NetworkLoggerPlugin(configuration: .init(logOptions: .verbose)),
DisableCookiePlugin()
]

Resources