I am writing an AngularJs app to test an API we developed. The app uses the $http object to make requests to the API. One of the asks is that after the call it's possible to review the raw HTTP (headers and bodies) Request/Response, similarly to what's available in Fiddler via Raw tabs.
Is it something that $http provides out of the box?
If not, it appears that the only challenge is gaining access to the actual request http headers. It's easy to get the response headers and request/response bodies, but not sure how to get the actual request headers.
Thanks.
If you are using $http service to make your API calls, you can use Interceptors to achieve what you want.
Here is what docs tell us about them:
For purposes of global error handling, authentication, or any kind of synchronous or asynchronous pre-processing of request or postprocessing of responses, it is desirable to be able to intercept requests before they are handed to the server and responses before they are handed over to the application code that initiated these requests. The interceptors leverage the promise APIs to fulfill this need for both synchronous and asynchronous pre-processing.
You can find more in depth explanation in the official docs. For example, here.
Also, there are some questions about interceptors on this site. There are some examples of their usage for displaying loading screen in applications: here, here and, probably, somewhere else.
Hope, this helps.
Yes, AngularJs is wrapped around some JQuery or internally JQlite if JQuery is not present and written in Javascript and it provides some pre-defined services. A typical service looks like the following.
AngularJS docs: tutorial step 5
$ Prefix Naming Convention You can create your own services, and in
fact we will do exactly that in step 11. As a naming convention,
Angular's built-in services, Scope methods and a few other Angular
APIs have a $ prefix in front of the name.
The $ prefix is there to namespace Angular-provided services. To
prevent collisions it's best to avoid naming your services and models
anything that begins with a $.
If you inspect a Scope, you may also notice some properties that begin
with $$. These properties are considered private, and should not be
accessed or modified.
angular.module('myApp')
.factory('myService', function ($http, $injector) {
'use strict';
return $http.get('/endpoint')
.then(function () {
return $injector.get('endpoint');
}
.error(function () {
// handle error
}
};
})
Have a look a the image in AngularJS docs which shows a number of services with the $ prefix. Mostly, wrappers over service. It is reserved. More at FAQ.
Related
I have an angular application. From frontend I can set some value. This value is something like config, which can be changed.
It is simple string variable. How to attach this config to each REST request ?
I ask mainly about approach.
Maybe pass it via headers is good idea ?
For angular 1.x, write an Interceptor:
For purposes of global error handling, authentication, or any kind of
synchronous or asynchronous pre-processing of request or
postprocessing of responses, it is desirable to be able to intercept
requests before they are handed to the server and responses before
they are handed over to the application code that initiated these
requests
For angular 2.x / 4.x, RequestOptions should be the key to solve your problem. Set base url for angular 2 http requests
I'm using angular2, my solution is create a Service and inject "Http" dependency, then write two methods "get", "post", these methods add an entry to header before calling "Http", in other component / service, I just inject this Service class, then call its "get" or "post".
Your code should be somewhat like this If your working in angular 1.3 or less
The data should be sent as body data to server
var basecall = Restangular.all('url');
bascall.post($scope.config).then(function(data){
})
My apps are using many web services on the intranet, and url-s for those depend on the server environment.
My apps are hosted on IIS, which adds an HTTP response header like this: Environment: DEV, so every web app knows in which server environment it is running, and thus which intranet servers it must use to call all the services.
Each of my angular apps uses a service that issues a simple GET against the app's own root just to get any response with the environment name in it, and set configuration accordingly.
Question:
How should an angular app implement such a service that would execute as the very first thing in the application, and make sure that while it is getting that first response, nothing in the app tries to execute an HTTP request against other services, or even try to use any configuration provided by my environment service?
Is there a way to implement such a service in angular that could block every other service / factory in the application till it is done initializing itself?
I have many other services in the app, and none of them really know what to do till my environment service has finished its initialization.
UPDATE
Looking at it from another angle.... is it possible to implement such an interceptor in angular that could do the following?:
execute an HTTP request and block the app's execution till it gets a response
make information from the response available throughout the app as a service/factory/config.
Angular lifecycle could be one solution. Using the angular.config() phase you could peek at the headers of the HTTP service.
Create a factory called 'httpInterceptor'
function httpInterceptors(siteConfig, $q, $injector) {
return {
response: function(data, status, headers) {
siteConfig.setEnvironment(headers['Environment']);
return data;
}
};
)
Then in angular.config()
$httpProvider.interceptors.push('httpInterceptor');
If you truly want to block the other option is to use UI router resolve property to block routes loading until the request has been made https://github.com/angular-ui/ui-router/wiki you can add the resolve method to the root state.
Resolve
You can use resolve to provide your controller with content or data that > is custom to the state. resolve is an optional map of dependencies which > should be injected into the controller.
If any of these dependencies are promises, they will be resolved and converted to a value before the controller is instantiated and the $stateChangeSuccess event is fired.
I want to test my code with real API calls (so I can test the API as well, and when I change the API I don't have to change the JS test as well, and a lot more benefits.) instead of the regular $httpBackend.expectPOST('http://api.com/login').response(200).
Essentially, I want to test a ProductsController that expects to be logged in through an AuthService.login() method and receive a list of products through ui-router's resolve feature.
In this case, the login method receives data that needs to be used to gather products.
From the $httpBackend documentation found here: https://docs.angularjs.org/api/ngMockE2E/service/$httpBackend
As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application is being developed with the real backend api replaced with a mock, it is often desirable for certain category of requests to bypass the mock and issue a real http request (e.g. to fetch templates or static files from the webserver). To configure the backend with this behavior use the passThrough request handler of when instead of respond
So, something like: $httpBackend.whenGET(/.*/).passThrough(); should suffice.
I would like to know whether we can create a provider in angularjs which will replace the $http operation .which means where we can use this provider in other modules where we can make use of these $http operation.
The reason why provider has to be taken is because we can configure the http parameters like the api path, request type .
Also can we have logging/exception handling mechanism inside the provider so that the modules(eg: any other factories) which inherit the provider wont need to do any extra logging/exception mechanisms.
Is there any way to have some loading screen using this provider when http requests are made ?
For the things you mentioned, you don't need another provider, because $http has the concept of interceptors.
Interceptors can specify different callbacks to be executed at different phases:
request (runs before any request is sent): It can modify the configuration (e.g. the request URL, method etc). It could also be used to show some loading message/animation (e.g. using some property on the $rootScope).
requestError (runs when there is an error before sending the request): It can be used for logging, recovering, exception handling.
response (runs after any response is received): It can be used for logging. It could also be used to hide the loading message/animation. (Don't forget to also handle this on response error.)
responseError (runs when there is an error regarding the response (e.g. bad request)): It can be used for logging, recovering, exception handling.
If interceptors do not cover your needs, you could use $provide's decorator to monkey-patch, augment or totally replace the $http service:
.config(function ($provide) {
$provide.decorator('$http', function ($delegate) {
var newHttp = $delegate; // or a totally new object
// ...monkey-patch newHttp or define new methods or whatever
return newHttp;
});
});
I am down to a choice between angularjs and dojo as my front end MV* framework. One particular functionality which in my mind is critical is the ability to do unobtrusive and transparent authentication. I was extremely impressed with angular's capability in this regard using http interceptors. See http://www.espeo.pl/2012/02/26/authentication-in-angularjs-application for a good sample implementation/explanation.
It allows one to queue up any and all 401 responses while waiting for successful login and then re-transmit them once login is successful by using a combination of broadcast events, event handling, and http interceptor (plus a request queue). The overhead on each request appears to be minimal.
I wanted to compare the ability of dojo to do the same, but from my examination it does not appear to be possible. Examining the dojo documentation, it appears that this would probably have been possible in dojo 1.4 using the ioPipline, but that that is deprecated in favor of dojo/request/notify which does not appear to provide as low-level of an interception (specifically it doesn't appear to give access to the request object when an error is received). it is also not clear if it is possible to modify or replace the response from within the notified function...
Can anyone point me to a clear example of this having been accomplished using dojo's request/notify service or an alternate methodology using dojo? Critical requirements are that the authentication be transparent to the protected functions/controllers/objects (they should simply receive a promise which is eventually fulfilled), that the authentication code be able to be centralized (it should not require modification to every object/event/etc that makes a request), and that it should be secure (in the sense that both authentication/authorization should happen on the server side and no javascript manipulation should be able to bypass that requirement)...
You can register handlers within dojo/request/registry to intercept and handle requests made using dojo/request any way you want. Here’s a modified (untested, probably slightly defective) example based on the reference guide:
require([ "dojo/request/registry", "dojo/request/xhr" ], function (registry, xhr) {
request.register(function (url, options) {
return xhr(url, options).response.then(function (response) {
if (response.status === 401) {
// retry later
}
return response;
});
}, true);
});
With the above example, any request made with dojo/request will be intercepted and the method provided will be called. If you wanted to conditionally only match certain requests with this handler, you can pass another tester function as the first argument. This is detailed in the reference guide linked above.
All your handler function then needs to do is return a promise that will eventually resolve to the expected data.