From 6fe3a1de7fc452d3e1240be392333126981e3516 Mon Sep 17 00:00:00 2001 From: Quentin Focheux Date: Tue, 26 Jan 2021 19:06:42 +0100 Subject: [PATCH] feat(http): expose a list of human-readable http status codes (#23548) They aim to improve code readability. Since they are defined by `const enum` they have zero runtime performance impact over just using constant literals. Fixes #23543 PR Close #23548 --- goldens/public-api/common/http/http.d.ts | 66 ++++++++++++++++++++ packages/common/http/public_api.ts | 2 +- packages/common/http/src/jsonp.ts | 5 +- packages/common/http/src/response.ts | 77 +++++++++++++++++++++++- packages/common/http/src/xhr.ts | 9 +-- 5 files changed, 151 insertions(+), 8 deletions(-) diff --git a/goldens/public-api/common/http/http.d.ts b/goldens/public-api/common/http/http.d.ts index 5dfb3aeee7..97865565b7 100644 --- a/goldens/public-api/common/http/http.d.ts +++ b/goldens/public-api/common/http/http.d.ts @@ -1709,6 +1709,72 @@ export declare interface HttpSentEvent { type: HttpEventType.Sent; } +export declare const enum HttpStatusCode { + Continue = 100, + SwitchingProtocols = 101, + Processing = 102, + EarlyHints = 103, + Ok = 200, + Created = 201, + Accepted = 202, + NonAuthoritativeInformation = 203, + NoContent = 204, + ResetContent = 205, + PartialContent = 206, + MultiStatus = 207, + AlreadyReported = 208, + ImUsed = 226, + MultipleChoices = 300, + MovedPermanently = 301, + Found = 302, + SeeOther = 303, + NotModified = 304, + UseProxy = 305, + Unused = 306, + TemporaryRedirect = 307, + PermanentRedirect = 308, + BadRequest = 400, + Unauthorized = 401, + PaymentRequired = 402, + Forbidden = 403, + NotFound = 404, + MethodNotAllowed = 405, + NotAcceptable = 406, + ProxyAuthenticationRequired = 407, + RequestTimeout = 408, + Conflict = 409, + Gone = 410, + LengthRequired = 411, + PreconditionFailed = 412, + PayloadTooLarge = 413, + UriTooLong = 414, + UnsupportedMediaType = 415, + RangeNotSatisfiable = 416, + ExpectationFailed = 417, + ImATeapot = 418, + MisdirectedRequest = 421, + UnprocessableEntity = 422, + Locked = 423, + FailedDependency = 424, + TooEarly = 425, + UpgradeRequired = 426, + PreconditionRequired = 428, + TooManyRequests = 429, + RequestHeaderFieldsTooLarge = 431, + UnavailableForLegalReasons = 451, + InternalServerError = 500, + NotImplemented = 501, + BadGateway = 502, + ServiceUnavailable = 503, + GatewayTimeout = 504, + HttpVersionNotSupported = 505, + VariantAlsoNegotiates = 506, + InsufficientStorage = 507, + LoopDetected = 508, + NotExtended = 510, + NetworkAuthenticationRequired = 511 +} + export declare interface HttpUploadProgressEvent extends HttpProgressEvent { type: HttpEventType.UploadProgress; } diff --git a/packages/common/http/public_api.ts b/packages/common/http/public_api.ts index 8a434169d7..2e3f588d6d 100644 --- a/packages/common/http/public_api.ts +++ b/packages/common/http/public_api.ts @@ -14,6 +14,6 @@ export {JsonpClientBackend, JsonpInterceptor} from './src/jsonp'; export {HttpClientJsonpModule, HttpClientModule, HttpClientXsrfModule, HttpInterceptingHandler as ɵHttpInterceptingHandler} from './src/module'; export {HttpParameterCodec, HttpParams, HttpParamsOptions, HttpUrlEncodingCodec} from './src/params'; export {HttpRequest} from './src/request'; -export {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpResponseBase, HttpSentEvent, HttpUploadProgressEvent, HttpUserEvent} from './src/response'; +export {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpProgressEvent, HttpResponse, HttpResponseBase, HttpSentEvent, HttpStatusCode, HttpUploadProgressEvent, HttpUserEvent} from './src/response'; export {HttpXhrBackend, XhrFactory} from './src/xhr'; export {HttpXsrfTokenExtractor} from './src/xsrf'; diff --git a/packages/common/http/src/jsonp.ts b/packages/common/http/src/jsonp.ts index aefedf20c0..e5be963497 100644 --- a/packages/common/http/src/jsonp.ts +++ b/packages/common/http/src/jsonp.ts @@ -12,7 +12,8 @@ import {Observable, Observer} from 'rxjs'; import {HttpBackend, HttpHandler} from './backend'; import {HttpRequest} from './request'; -import {HttpErrorResponse, HttpEvent, HttpEventType, HttpResponse} from './response'; +import {HttpErrorResponse, HttpEvent, HttpEventType, HttpResponse, HttpStatusCode} from './response'; + // Every request made through JSONP needs a callback name that's unique across the // whole page. Each request is assigned an id and the callback name is constructed @@ -169,7 +170,7 @@ export class JsonpClientBackend implements HttpBackend { // returned. observer.next(new HttpResponse({ body, - status: 200, + status: HttpStatusCode.Ok, statusText: 'OK', url, })); diff --git a/packages/common/http/src/response.ts b/packages/common/http/src/response.ts index e9ccd95422..8ce1a92f3a 100644 --- a/packages/common/http/src/response.ts +++ b/packages/common/http/src/response.ts @@ -191,7 +191,7 @@ export abstract class HttpResponseBase { statusText?: string, url?: string, }, - defaultStatus: number = 200, defaultStatusText: string = 'OK') { + defaultStatus: number = HttpStatusCode.Ok, defaultStatusText: string = 'OK') { // If the hash has values passed, use them to initialize the response. // Otherwise use the default values. this.headers = init.headers || new HttpHeaders(); @@ -348,3 +348,78 @@ export class HttpErrorResponse extends HttpResponseBase implements Error { this.error = init.error || null; } } + +/** + * Http status codes. + * As per https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml + * @publicApi + */ +export const enum HttpStatusCode { + Continue = 100, + SwitchingProtocols = 101, + Processing = 102, + EarlyHints = 103, + + Ok = 200, + Created = 201, + Accepted = 202, + NonAuthoritativeInformation = 203, + NoContent = 204, + ResetContent = 205, + PartialContent = 206, + MultiStatus = 207, + AlreadyReported = 208, + ImUsed = 226, + + MultipleChoices = 300, + MovedPermanently = 301, + Found = 302, + SeeOther = 303, + NotModified = 304, + UseProxy = 305, + Unused = 306, + TemporaryRedirect = 307, + PermanentRedirect = 308, + + BadRequest = 400, + Unauthorized = 401, + PaymentRequired = 402, + Forbidden = 403, + NotFound = 404, + MethodNotAllowed = 405, + NotAcceptable = 406, + ProxyAuthenticationRequired = 407, + RequestTimeout = 408, + Conflict = 409, + Gone = 410, + LengthRequired = 411, + PreconditionFailed = 412, + PayloadTooLarge = 413, + UriTooLong = 414, + UnsupportedMediaType = 415, + RangeNotSatisfiable = 416, + ExpectationFailed = 417, + ImATeapot = 418, + MisdirectedRequest = 421, + UnprocessableEntity = 422, + Locked = 423, + FailedDependency = 424, + TooEarly = 425, + UpgradeRequired = 426, + PreconditionRequired = 428, + TooManyRequests = 429, + RequestHeaderFieldsTooLarge = 431, + UnavailableForLegalReasons = 451, + + InternalServerError = 500, + NotImplemented = 501, + BadGateway = 502, + ServiceUnavailable = 503, + GatewayTimeout = 504, + HttpVersionNotSupported = 505, + VariantAlsoNegotiates = 506, + InsufficientStorage = 507, + LoopDetected = 508, + NotExtended = 510, + NetworkAuthenticationRequired = 511 +} diff --git a/packages/common/http/src/xhr.ts b/packages/common/http/src/xhr.ts index 2618e8417a..056f516b17 100644 --- a/packages/common/http/src/xhr.ts +++ b/packages/common/http/src/xhr.ts @@ -12,7 +12,8 @@ import {Observable, Observer} from 'rxjs'; import {HttpBackend} from './backend'; import {HttpHeaders} from './headers'; import {HttpRequest} from './request'; -import {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpJsonParseError, HttpResponse, HttpUploadProgressEvent} from './response'; +import {HttpDownloadProgressEvent, HttpErrorResponse, HttpEvent, HttpEventType, HttpHeaderResponse, HttpJsonParseError, HttpResponse, HttpStatusCode, HttpUploadProgressEvent} from './response'; + const XSSI_PREFIX = /^\)\]\}',?\n/; @@ -142,7 +143,7 @@ export class HttpXhrBackend implements HttpBackend { } // Read status and normalize an IE9 bug (https://bugs.jquery.com/ticket/1450). - const status: number = xhr.status === 1223 ? 204 : xhr.status; + const status: number = xhr.status === 1223 ? HttpStatusCode.NoContent : xhr.status; const statusText = xhr.statusText || 'OK'; // Parse headers from XMLHttpRequest - this step is lazy. @@ -168,14 +169,14 @@ export class HttpXhrBackend implements HttpBackend { // The body will be read out if present. let body: any|null = null; - if (status !== 204) { + if (status !== HttpStatusCode.NoContent) { // Use XMLHttpRequest.response if set, responseText otherwise. body = (typeof xhr.response === 'undefined') ? xhr.responseText : xhr.response; } // Normalize another potential bug (this one comes from CORS). if (status === 0) { - status = !!body ? 200 : 0; + status = !!body ? HttpStatusCode.Ok : 0; } // ok determines whether the response will be transmitted on the event or