* Processes a request and returns a stream of response events. * @param req The request object. * @returns An observable of the response events.
(req: HttpRequest<any>)
| 122 | * @returns An observable of the response events. |
| 123 | */ |
| 124 | handle(req: HttpRequest<any>): Observable<HttpEvent<any>> { |
| 125 | // Quick check to give a better error message when a user attempts to use |
| 126 | // HttpClient.jsonp() without installing the HttpClientJsonpModule |
| 127 | if (req.method === 'JSONP') { |
| 128 | throw new RuntimeError( |
| 129 | RuntimeErrorCode.MISSING_JSONP_MODULE, |
| 130 | (typeof ngDevMode === 'undefined' || ngDevMode) && |
| 131 | `Cannot make a JSONP request without JSONP support. To fix the problem, either add the \`withJsonpSupport()\` call (if \`provideHttpClient()\` is used) or import the \`HttpClientJsonpModule\` in the root NgModule.`, |
| 132 | ); |
| 133 | } |
| 134 | |
| 135 | // Validate that the request is compatible with the XHR backend. |
| 136 | ngDevMode && validateXhrCompatibility(req); |
| 137 | |
| 138 | // Check whether this factory has a special function to load an XHR implementation |
| 139 | // for various non-browser environments. We currently limit it to only `ServerXhr` |
| 140 | // class, which needs to load an XHR implementation. |
| 141 | const xhrFactory: XhrFactory & {ɵloadImpl?: () => Promise<void>} = this.xhrFactory; |
| 142 | const source: Observable<void | null> = |
| 143 | // Note that `ɵloadImpl` is never defined in client bundles and can be |
| 144 | // safely dropped whenever we're running in the browser. |
| 145 | // This branching is redundant. |
| 146 | // The `ngServerMode` guard also enables tree-shaking of the `from()` |
| 147 | // function from the common bundle, as it's only used in server code. |
| 148 | typeof ngServerMode !== 'undefined' && ngServerMode && xhrFactory.ɵloadImpl |
| 149 | ? from(xhrFactory.ɵloadImpl()) |
| 150 | : of(null); |
| 151 | |
| 152 | return source.pipe( |
| 153 | switchMap(() => { |
| 154 | // Everything happens on Observable subscription. |
| 155 | return new Observable((observer: Observer<HttpEvent<any>>) => { |
| 156 | // Start by setting up the XHR object with request method, URL, and withCredentials |
| 157 | // flag. |
| 158 | const xhr = xhrFactory.build(); |
| 159 | xhr.open(req.method, req.urlWithParams); |
| 160 | if (req.withCredentials) { |
| 161 | xhr.withCredentials = true; |
| 162 | } |
| 163 | |
| 164 | // Add all the requested headers. |
| 165 | req.headers.forEach((name, values) => xhr.setRequestHeader(name, values.join(','))); |
| 166 | |
| 167 | // Add an Accept header if one isn't present already. |
| 168 | if (!req.headers.has(ACCEPT_HEADER)) { |
| 169 | xhr.setRequestHeader(ACCEPT_HEADER, ACCEPT_HEADER_VALUE); |
| 170 | } |
| 171 | |
| 172 | // Auto-detect the Content-Type header if one isn't present already. |
| 173 | if (!req.headers.has(CONTENT_TYPE_HEADER)) { |
| 174 | const detectedType = req.detectContentTypeHeader(); |
| 175 | // Sometimes Content-Type detection fails. |
| 176 | if (detectedType !== null) { |
| 177 | xhr.setRequestHeader(CONTENT_TYPE_HEADER, detectedType); |
| 178 | } |
| 179 | } |
| 180 | |
| 181 | if (req.timeout) { |
nothing calls this directly
no test coverage detected