I found a few examples of using fullRequestInterceptor and httpConfig.timeout to allow canceling requests in restangular.
example 1 | example 2
this is how I'm adding the interceptor:
app.run(function (Restangular, $q) {
Restangular.addFullRequestInterceptor(function (element, operation, what, url, headers, params, httpConfig) {
I managed to abort the request by putting a resolved promise in timeout (results in an error being logged and the request goes out but is canceled), which is not what I want.
What I'm trying to do - I want to make the AJAX request myself with my own requests and pass the result back to whatever component that used Restangular. Is this possible?
I've been looking a restangular way to solve it, but I should have been looking for an angular way :)
Overriding dependency at runtime in AngularJS
Looks like you can extend $http before it ever gets to Restangular. I haven't tried it yet, but it looks like it would fit my needs 100%.
I'm using requestInterceptor a lot, but only to change parameters and headers of my request.
Basically addFullRequestInterceptor is helping you making change on your request before sending it. So why not changing the url you want to call ?
There is the httpConfig object that you can modify and return, and if it's close to the config of $http (and I bet it is) you can change the url and even method, and so change the original request to another one, entirely knew.
After that you don't need timeout only returning an httpConfig customise to your need.
RestangularConfigurer.addFullRequestInterceptor(function (element, operation, route, url, headers, params, httpConfig) {
httpConfig.url = "http://google.com";
httpConfig.method = "GET";
httpConfig.params = "";
return {
httpConfig: httpConfig
};
});
It will be pass on and your service or controller won't know that something change, that's the principle of interceptor, it allow you to change stuff and returning to be use by the next process a bit like a middleware. And so it will be transparent to the one making the call but the call will be made to what you want.
Related
My middleware need is to:
add an extra query param to requests made by a REST API client derived from GuzzleHttp\Command\Guzzle\GuzzleClient
I cannot do this directly when invoking APIs through the client because GuzzleClient uses an API specification and it only passes on "legal" query parameters. Therefore I must install a middleware to intercept HTTP requests after the API client prepares them.
The track I am currently on:
$apiClient->getHandlerStack()-push($myMiddleware)
The problem:
I cannot figure out the RIGHT way to assemble the functional Russian doll that $myMiddleware must be. This is an insane gazilliardth-order function scenario, and the exact right way the function should be written seems to be different from the extensively documented way of doing things when working with GuzzleHttp\Client directly. No matter what I try, I end up having wrong things passed to some layer of the matryoshka, causing an argument type error, or I end up returning something wrong from a layer, causing a type error in Guzzle code.
I made a carefully weighted decision to give up trying to understand. Please just give me a boilerplate solution for GuzzleHttp\Command\Guzzle\GuzzleClient, as opposed to GuzzleHttp\Client.
The HandlerStack that is used to handle middleware in GuzzleHttp\Command\Guzzle\GuzzleClient can either transform/validate a command before it is serialized or handle the result after it comes back. If you want to modify the command after it has been turned into a request, but before it is actually sent, then you'd use the same method of Middleware as if you weren't using GuzzleClient - create and attach middleware to the GuzzleHttp\Client instance that is passed as the first argument to GuzzleClient.
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Command\Guzzle\GuzzleClient;
use GuzzleHttp\Command\Guzzle\Description;
class MyCustomMiddleware
{
public function __invoke(callable $handler) {
return function (RequestInterface $request, array $options) use ($handler) {
// ... do something with request
return $handler($request, $options);
}
}
}
$handlerStack = HandlerStack::create();
$handlerStack->push(new MyCustomMiddleware);
$config['handler'] = $handlerStack;
$apiClient = new GuzzleClient(new Client($config), new Description(...));
The boilerplate solution for GuzzleClient is the same as for GuzzleHttp\Client because regardless of using Guzzle Services or not, your request-modifying middleware needs to go on GuzzleHttp\Client.
You can also use
$handler->push(Middleware::mapRequest(function(){...});
Of sorts to manipulate the request. I'm not 100% certain this is the thing you're looking for. But I assume you can add your extra parameter to the Request in there.
private function createAuthStack()
{
$stack = HandlerStack::create();
$stack->push(Middleware::mapRequest(function (RequestInterface $request) {
return $request->withHeader('Authorization', "Bearer " . $this->accessToken);
}));
return $stack;
}
More Examples here: https://hotexamples.com/examples/guzzlehttp/Middleware/mapRequest/php-middleware-maprequest-method-examples.html
I have a Web API app, initialized thusly:
app.UseCookieAuthentication();
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOAuthBearerTokens(OAuthOptions);
app.UseGoogleAuthentication();
For calls to most controllers, it works great. However, it also requires a bit of javascript before client-side service calls are made:
function getSecurityHeaders() {
var accessToken = sessionStorage["accessToken"] || localStorage["accessToken"];
if (accessToken) {
return { "Authorization": "Bearer " + accessToken };
}
return {};
}
The problem is that we have a certain type of controller (one that accesses files) where no javascript can be run during the call. For example, the call might be to:
http://mysite/mycontroller/file/filename.jpg
...where the value is assigned as the src attribute of an img tag. The call works, but Thread.CurrentPrincipal.Identity is unauthenticated with a null name, so there's currently not a way to enforce security.
I'm new to Web API, so it may be a dumb question, but what's the way around this? What switches do I need to flip to not require javascript to add security headers? I was considering trying to find a way to force an authorization header in an IAuthorizationFilter or something, but I'm not even sure that would work.
So I figured out the solution to my problem.
First, I needed to configure the app to use an authentication type of external cookies thusly:
//the line below is the one I needed to change
app.UseCookieAuthentication(AuthenticationType = DefaultAuthenticationTypes.ExternalCookie);
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
app.UseOAuthBearerTokens(OAuthOptions);
app.UseGoogleAuthentication();
Second, it turned out there was a line of code in my WebApiConfig file that was disabling reading the external cookie:
//this line needed to be removed
//config.SuppressDefaultHostAuthentication();
After that, I could see the external cookie from Google, which passed along an email address I could identify the user with.
I'm experiencing unexpected behaviour while trying to access query string parameters in a mojolicious websocket request. Say my request looks like this:
ws://127.0.0.1:3000/websock_action?item_id=1234
Then in my mojo controller code I try and get the value of item_id in any of the following ways:
#in mojo controller
my $item_id = $self->param('item_id');
my $item_id = scalar $self->param('item_id');
my $item_id = scalar $self->tx->req->url->query->param('item_id');
The issue is that the item_id I get is often from a previous request, whichever of these techniques I use. My app is currently being served with hypnotoad.
Are query string parameters supported on websocket requests in mojolicious? Is there a more reliable way to access them? Essentially I'd like to know if I'm trying to something that isn't supported, so I can know whether the problem is something specific to my app.
Thanks in advance for any help
I suspect that what is happening, is that the parameters are passed in the html request, which is then upgraded to a websocket request at which point they are no longer available.
As Daren said, pass the data in the Web-Socket data. Something like...
var ws = $.websocket("ws://127.0.0.1:3000/websock_action", {
events: { message: function(e) {}
});
ws.send('message', 1234);
I want to call another internal url from my scalatra 'controller'. I can't do a simple redirect, as there's some security settings that mean a user has access only to the first url.
Is there a way to do this?
get("/foo") {
servletContext.getRequestDispatcher("/bar").forward(request, response)
}
The get() method is defined as (similar to POST, et al):
def get(transformers : org.scalatra.RouteTransformer*)(action : => scala.Any) : org.scalatra.Route
Depends on what you mean by internal redirect, I presume you just want to execute another route's action. You have a few options of what you can do. This seems to be working for me:
val canonicalEndpoint = get("/first/route") {
//do things in here
}
Then you could subsequently do:
get("/second/route")( canonicalEndpoint.action )
And I think you would get your desired response.
I like saving the whole Route response of the get() as you may also want to use that with scalatra's url() function in routing.
I'd like to create filter which will switch request data. More precisely i'd like to change type of request inside filter (it have to be POST), add some values into post's Data, add return url, and redirect it to Controller's action which accepts only POST... and then in this action i'd like to return to first URL.
I've found something like...
Response.Redirect with POST instead of Get?
but i'm pretty sure i don't catch his idea completely and don't know is it useful in FIlter.
I've not found how to change request data... but useful was to
var controller = new MyController();
controller.ControllerContext = filterContext.Controller.ControllerContext;
controller.<action>(<parameters>); // it's action which accepts only POST, but here it doesn't matter
base.OnActionExecuting(filterContext);
Is there any better way to pass context or mayby... invoke Controller from current context? instead of creating new controller and calling his action?