canInitWithRequest method in custom NSURLProtocol class is not triggered when using Alamofire - alamofire

I have a custom NSURLProtocol class to provide test data while I'm experimenting with Alamofire, but it doesn't seem to be used when making requests via the Manager request method.
This request goes through and returns a result just fine, but does not trigger canInitWithRequest:
NSURLProtocol.registerClass(DBDummyURLProtocol)
class MyURLRequestConvertible : URLRequestConvertible {
var URLRequest: NSURLRequest {
return NSURLRequest(URL: NSURL(scheme: "http", host: "cnn.com", path: "/")!)
}
}
var myURLRequestConvertible = MyURLRequestConvertible();
Manager.sharedInstance.request(myURLRequestConvertible)
If I use a simple NSURLConnection, the canInitWithRequest method is called as I expected:
NSURLProtocol.registerClass(DBDummyURLProtocol)
var request = NSURLRequest(URL: NSURL(scheme: "http", host: "cnn.com", path: "/")!)
NSURLConnection(request: request, delegate:nil, startImmediately:true)
Am I doing something wrong? Should this work with Alamofire?

Alamofire uses NSURLSession internally which does not respect the protocol classes registered using NSURLProtocol.registerClass(). Instead it uses a NSURLSessionConfiguration object which has a protocolClasses property.
Unfortunately this configuration cannot be changed since the session always returns a copy and the property is not writable.
What you can do instead is create your own instance of Alamofire.Manager and pass it a custom NSURLSessionConfiguration
let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
configuration.protocolClasses.insert(DBDummyURLProtocol.self, atIndex: 0)
let manager = Manager(configuration: configuration)
manager.request(.GET, "http://example.com")

Related

Can't perform HTTP Post Action from Logic App to Asp.net Core Web API

I've built many Logic Apps. I've also integrated with the Logic App API. For some reason, a Post request to an Asp.net Core Web API won't work. It works in Postman, but I can't get Logic Apps to complete the request.
The request arrives at my Web API. I can step through it during a remote debug session. I'm using the [FromBody] decorator on the API method. All the string values in the object are null.
Logic App Headers
Accept = "application/json"
ContentType = "application/json"
ContentLength = "35"
Host = "****.centralus.logic.azure.com"
API method
[HttpPost]
[Route("CreateSomething")]
public async Task<IActionResult> CreateSomething([FromBody] MyObject object)
{
//Create something great
}
I think it might have something to do with the Headers. I noticed that the Postman request won't succeed unless I check the Host and Content-Length box in the Headers section. According to this article, Logic Apps ignores those Headers.
https://learn.microsoft.com/en-us/azure/connectors/connectors-native-http
I've built the HTTP Post Action using the API as well as configured it manually using the Logic App UI in Azure.
By the way, does anyone know the Expression that will automatically calculate the ContentLength?
UPDATE:
I finally figured this out. I had to do some Ninja coding crap to make this work. I'll post my solution tomorrow.
Does anyone know how to make this work? Thanks in advance!
When you use the Logic App API to programmatically create Logic Apps, you have to specify the Body class for when you do something like an HTTP Post. When the Body JSON displayed in the designer, it contained a single object with the objects properties. My API method could not handle this. The key was to simply post the properties in the JSON Body. To make matters worse, I'm doing two HTTP Posts in this particular Logic App. When I tried to add my object properties to the existing Body class, it caused my other HTTP Post to stop working. To overcome this, I had to create a Body2 class with the objects properties. I then had to use the following line of code to replace body2 with body before adding the JSON to the Logic App API call.
This did not work.
body = new Body()
{
object = new Object()
{
//Properties
}
}
This worked.
body2 = new Body2()
{
Type = 0,
Description = "#{items('For_each_2')?['day']?['description']}",
Locations = item.Locations,
Cold = "#{items('For_each_2')?['temperature']?['cold']?['value']}",
Hot = "#{items('For_each_2')?['temperature']?['hot']?['value']}",
Hide = 0
}
Notice I used Replace on body2.
var options = new JsonSerializerOptions { WriteIndented = true, IgnoreNullValues = true};
string jsonString = ReplaceFirst(JsonSerializer.Serialize(myApp, options), "schema", "$schema").Replace("_else", "else").Replace("_foreach", "foreach").Replace("body2", "body");

InversifyJS: dependency instantiation per HTTP Request

I'm using Inversify.JS in a project with Express. I would like to create a connection to a Neo4J Database, and this process has two objets:
The driver object - Could be shared across the application and created one time only
The session object - Each HTTP request should create a session against the driver, whose lifecyle is the same as the http request lifecycle (as long as the request ends, the connection is destroyed)
Without Insersify.JS, this problem is solved using a simple algorithm:
exports.getSession = function (context) { // 'context' is the http request
if(context.neo4jSession) {
return context.neo4jSession;
}
else {
context.neo4jSession = driver.session();
return context.neo4jSession;
}
};
(example: https://github.com/neo4j-examples/neo4j-movies-template/blob/master/api/neo4j/dbUtils.js#L13-L21)
To create a static dependency for the driver, I can inject a constant:
container.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());
How can I create a dependency instantiated only once per request and retrieve them from the container?
I suspect I must invoke the container on a middleware like this:
this._express.use((request, response, next) => {
// get the container and create an instance of the Neo4JSession for the request lifecycle
next();
});
Thanks in advance.
I see two solutions to your problem.
use inRequestScope() for DbDriver dependency. (available since 4.5.0 version). It will work if you use single composition root for one http request. In other words you call container.get() only once per http request.
create child container, attach it to response.locals._container and register DbDriver as singleton.
let appContainer = new Container()
appContainer.bind(SomeDependencySymbol).to(SomeDependencyImpl);
function injectContainerMiddleware(request, response, next) {
let requestContainer = appContainer.createChildContainer();
requestContainer.bind<DbDriver>("DbDriver").toConstantValue(new Neo4JDbDriver());
response.locals._container = requestContainer;
next();
}
express.use(injectContainerMiddleware); //insert injectContainerMiddleware before any other request handler functions
In this example you can retrieve DbDriver from response.locals._container in any request handler/middleware function registered after injectContainerMiddleware and you will get the same instance of DbDriver
This will work, but I'm not sure how performant it is. Additionally I guess that you may need to somehow dispose requestContainer (unbind all dependencies and remove reference to parent container) after http request is done.

how to mock long json response via dojo registry?

I'm trying to follow this article to mock some response.
I'm porting mocked data from existing mocking service. There are some really long json responses, such as:
"{\"Layout\":{\"Id\":\
.......
"Image1\":\"test.png\",\"Image2\":\"\",\"multi\":[\"test1\",\"test2\",\"test3\"]}}"
There are a few hundred lines in the "......". Is there a easy way of doing this? Can I load the response from a file when I register the mock response?
It should be trivial to set up a mock provider to respond with data from separate local static files. Just return the result of sending an XHR (with dojo/request/xhr) to the desired static resource.
The following example assumes you have a static JSON resource in a path relative to your mock provider module:
define([
'require',
'dojo/request/registry',
'dojo/request/xhr'
], function (require, registry, xhr) {
registry.register('/service', function (url, options) {
// Presuming you're already passing handleAs: 'json' in options anyway,
// you can just pass options to the xhr call as-is.
return xhr(require.toUrl('./data/sample.json'), options);
});
...
return registry;
});

Sencha Touch ajax prefilter, supply url root for all ajax requests

In a Sencha touch aplication, can I use some sort of ajax prefilter and supply a URL root for all my requests (from stores and models)?
One more thing,
Is there a way to add a AUTH-TOKEN header, alto to every ajax request?
Thank you!
Ext.Ajax.request is a singleton instance. You can tap on beforerequest event and change/modify url, add/remove headers and do all other modification as needed. This way you can capture all your ajax request. You should be able to do this in your app.launch function.
Ext.Ajax.on('beforerequest', function(conn, request, eOpts){
// Your implementaion here. change request.url, request.headers etc
});
If you're setting the URL on your store proxies via Ext.data.proxy.Ajax.url, you could do this in one of two ways.
One: you can extend (or override) the class, adding the logic yourself.
Two: you could configure your URLs as such:
//someplace define this...
var urlPrefix = function() {
return '/path/to/API/';
};
//in your store/proxy
Ext.define('MyApp.store.Foo', {
config : {
proxy : {
type : 'ajax',
url : urlPrefix() + 'API_endpoint'
}
}
});
I've done that a bunch of times before.
As for your Auth headers, you can override Ext.data.Connection to include additional headers. The key here is that you would need to override it very early in the application lifetime, because other classes have unique instances of Ext.data.Connection (for example, Ext.Ajax).
But before giving a recommendation on how to apply the headers globally, I'd need to know more about what you needed to do. There's many things to consider before doing that.

Setting the HTTP Accept header for JsonRestStore

I'm using JsonRestStore but would like to add a custom Accept header to it. What's the best way to go about this?
This is similar to how the dijit.layout.ContentPane allows you to affect the underlying XHR by setting ioArgs. So the question could be "what is JsonRestStore's ioArgs?"
I'm using declarative syntax, but would gladly like to see both methods...
(Please note: I'm not interested in hacking my way around this by modifying the base XHR.)
Your best bet is providing a custom service to JsonRestStore. The easiest way I found of doing this is building the service from dojox.rpc.Rest. In the constructor you can provide a function to create the request arguments for all XHR requests. E.g.
function getRequest(id, args) {
return {
url: '/service/' + id,
handleAs: 'json',
sync: false,
headers: {
Accept: 'your custom header'
}
}
}
var service = new dojo.rpc.Rest('/service/', true /*isJson*/,
undefined /*schema*/, getRequest);
var store = new dojox.data.JsonRestStore({ service: service });
This completely ignores the args parameter that can include sorting and range arguments to your service.
These links will provide more information:
Use Dojo's JsonRestStore with your REST services: IBM developerWorks article with a more advanced and customizable solution
RESTful JSON + Dojo Data: Sitepen post
dojox.rpc.Rest source file (look for service._getRequest)