Skip to content

Commit 3d80ee1

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents ec82cef + 4b9be8f commit 3d80ee1

File tree

9 files changed

+203
-218
lines changed

9 files changed

+203
-218
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
"build.android": "bash src-native/android/build.sh",
99
"build.ios": "bash src-native/ios/build.sh",
1010
"build.native": "npm run build.android && npm run build.ios",
11+
"build.angular": "lerna run build.angular",
1112
"build": "lerna run build",
1213
"demo.ios": "npm run build && cd ./demo && tns run ios",
1314
"demo.android": "npm run build && cd ./demo && tns run android",
@@ -88,6 +89,7 @@
8889
"descriptions": {
8990
"build": "Build the plugin",
9091
"build.all": "Build the plugin for all platforms",
92+
"build.angular": "Build the plugin for Angular",
9193
"clean": "Clean the local environment.",
9294
"demo.vue.android": "Runs the Vue demo on Android.",
9395
"demo.vue.ios": "Runs the Vue demo on iOS.",

packages/https/tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44
"rootDir": "../../src/https",
55
"outDir": "./"
66
},
7-
"include": ["../../src/https/**/*", "../../references.d.ts", "../../tools/references.d.ts", "../../src/references.d.ts"]
7+
"include": ["../../src/https/**/*", "../../references.d.ts", "../../tools/references.d.ts", "../../src/references.d.ts"],
8+
"exclude": ["../../src/https/angular/**"]
89
}
Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
import { Injectable } from '@angular/core';
2-
import { HttpRequest } from '@angular/common/http';
3-
4-
@Injectable()
5-
export class ExcludedService {
6-
private readonly _urlList: Array<string> = [ ];
7-
8-
public static isMultipartFormRequest(request: HttpRequest<any>): boolean {
9-
const headers = request.headers.get('Content-Type');
10-
return headers ? headers.includes('application/x-www-form-urlencoded') : false;
11-
}
12-
13-
public addUrl(domain: string): void {
14-
this._urlList.push(domain);
15-
}
16-
17-
public contains(needle: string): boolean {
18-
return Boolean(this._urlList.filter((url) => url === needle).length);
19-
}
20-
21-
public skipSslPinning(request: HttpRequest<any>): boolean {
22-
return this.contains(request.url);
23-
}
24-
}
1+
import { Injectable } from '@angular/core';
2+
import { HttpRequest } from '@angular/common/http';
3+
4+
@Injectable()
5+
export class ExcludedService {
6+
private readonly _urlList: string[] = [];
7+
8+
public static isMultipartFormRequest(request: HttpRequest<any>): boolean {
9+
const headers = request.headers.get('Content-Type');
10+
return headers ? headers.includes('application/x-www-form-urlencoded') : false;
11+
}
12+
13+
public addUrl(domain: string): void {
14+
this._urlList.push(domain);
15+
}
16+
17+
public contains(needle: string): boolean {
18+
return Boolean(this._urlList.filter((url) => url === needle).length);
19+
}
20+
21+
public skipSslPinning(request: HttpRequest<any>): boolean {
22+
return this.contains(request.url);
23+
}
24+
}

src/https/angular/ng-package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
{
22
"dest": "../../../packages/https/angular",
33
"lib": {
4-
"entryFile": "index.ts"
4+
"entryFile": "index.ts"
55
},
66
"allowedNonPeerDependencies": [
7-
"."
7+
"."
88
]
9-
}
9+
}
Lines changed: 118 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -1,124 +1,118 @@
1-
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
2-
import {
3-
HttpErrorResponse,
4-
HttpEvent,
5-
HttpHeaders,
6-
HttpRequest,
7-
HttpResponse,
8-
XhrFactory
9-
} from '@angular/common/http';
10-
import { Observable, from, throwError } from 'rxjs';
11-
import { catchError, map } from 'rxjs/operators';
12-
import { NSFileSystem, NsHttpBackEnd } from '@nativescript/angular';
13-
import {
14-
Headers,
15-
HttpsRequestObject,
16-
HttpsRequestOptions,
17-
HttpsResponse,
18-
request as httpsRequest
19-
} from '../request';
20-
import { ExcludedService } from './excluded.service';
21-
22-
/** Https request default options. */
23-
export type HttpsRequestDefaultOptions
24-
= Pick<HttpsRequestOptions, 'timeout' | 'allowLargeResponse' | 'cachePolicy' | 'cookiesEnabled'>
25-
& { useLegacy?: boolean; };
26-
27-
/** Page size injection token. */
28-
export const HTTPS_REQUEST_DEFAULT_OPTIONS
29-
= new InjectionToken<HttpsRequestDefaultOptions>('HTTPS_REQUEST_DEFAULT_OPTIONS');
30-
31-
@Injectable()
32-
export class NativeScriptHttpXhrBackend extends NsHttpBackEnd {
33-
constructor(
34-
xhrFactory: XhrFactory,
35-
nsFileSystem: NSFileSystem,
36-
private readonly _excludedService: ExcludedService,
37-
@Optional()
38-
@Inject(HTTPS_REQUEST_DEFAULT_OPTIONS)
39-
private readonly _defaults?: HttpsRequestDefaultOptions
40-
) {
41-
super(xhrFactory, nsFileSystem);
42-
}
43-
44-
public handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
45-
let result: Observable<HttpEvent<any>>;
46-
if (this._isLocalRequest(req.url) || this._excludedService.skipSslPinning(req)) {
47-
result = super.handle(req);
48-
} else {
49-
result = this._request(req)
50-
.pipe(
51-
map((response: HttpsResponse) => {
52-
return new HttpResponse({
53-
body: response.content,
54-
headers: new HttpHeaders(response.headers),
55-
status: response.statusCode,
56-
statusText: response.reason,
57-
url: req.url
58-
});
59-
}),
60-
catchError((error) => {
61-
return throwError(() => new HttpErrorResponse({
62-
status: error.status,
63-
headers: error.headers,
64-
statusText: error.statusText,
65-
url: req.url
66-
}));
67-
})
68-
);
69-
}
70-
71-
return result;
72-
}
73-
74-
private _isLocalRequest(url: string): boolean {
75-
return url.indexOf('~') === 0 || url.indexOf('/') === 0;
76-
}
77-
78-
private _request(request: HttpRequest<any>) {
79-
const method = request.method as ('GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD');
80-
return from(httpsRequest({
81-
url: request.url,
82-
method,
83-
headers: this._mapHeaders(request),
84-
params: this._mapParams(request),
85-
body: request.body,
86-
timeout: this._defaults?.timeout ?? 3 * 60,
87-
allowLargeResponse: this._defaults?.allowLargeResponse ?? true,
88-
cachePolicy: this._defaults?.cachePolicy ?? 'noCache',
89-
cookiesEnabled: this._defaults?.cookiesEnabled ?? false
90-
}, this._defaults?.useLegacy ?? true));
91-
}
92-
93-
private _mapHeaders(request: HttpRequest<any>): Headers {
94-
const headerKeys = request.headers.keys();
95-
const headers = headerKeys.reduce<Headers>((accumulator, key) => {
96-
const values = request.headers.getAll(key);
97-
if (values !== null && values !== undefined) {
98-
accumulator[key] = values.length > 1 ? values.join(' ') : values[0];
99-
}
100-
return accumulator;
101-
}, { });
102-
103-
if (Object.keys(headers).length) {
104-
return headers;
105-
}
106-
107-
return {
108-
'Content-Type': 'application/json',
109-
'Accept': 'application/json'
110-
};
111-
}
112-
113-
private _mapParams(request: HttpRequest<any>): HttpsRequestObject {
114-
const paramKeys = request.params.keys();
115-
const params = paramKeys.reduce<HttpsRequestObject>((accumulator, key) => {
116-
const values = request.params.getAll(key);
117-
if (values !== null && values !== undefined) {
118-
accumulator[key] = values.length > 1 ? values : values[0];
119-
}
120-
return accumulator;
121-
}, { });
122-
return params;
123-
}
124-
}
1+
import { Inject, Injectable, InjectionToken, Optional } from '@angular/core';
2+
import { HttpErrorResponse, HttpEvent, HttpHeaders, HttpRequest, HttpResponse, XhrFactory } from '@angular/common/http';
3+
import { Observable, from, throwError } from 'rxjs';
4+
import { catchError, map } from 'rxjs/operators';
5+
import { NSFileSystem, NsHttpBackEnd } from '@nativescript/angular';
6+
import { Headers, HttpsRequestObject, HttpsRequestOptions, HttpsResponse, request as httpsRequest } from '@nativescript-community/https';
7+
import { ExcludedService } from './excluded.service';
8+
9+
/** Https request default options. */
10+
export type HttpsRequestDefaultOptions = Pick<HttpsRequestOptions, 'timeout' | 'allowLargeResponse' | 'cachePolicy' | 'cookiesEnabled'> & { useLegacy?: boolean };
11+
12+
/** Page size injection token. */
13+
export const HTTPS_REQUEST_DEFAULT_OPTIONS = new InjectionToken<HttpsRequestDefaultOptions>('HTTPS_REQUEST_DEFAULT_OPTIONS');
14+
15+
@Injectable()
16+
export class NativeScriptHttpXhrBackend extends NsHttpBackEnd {
17+
constructor(
18+
xhrFactory: XhrFactory,
19+
nsFileSystem: NSFileSystem,
20+
private readonly _excludedService: ExcludedService,
21+
@Optional()
22+
@Inject(HTTPS_REQUEST_DEFAULT_OPTIONS)
23+
private readonly _defaults?: HttpsRequestDefaultOptions
24+
) {
25+
super(xhrFactory, nsFileSystem);
26+
}
27+
28+
public handle(req: HttpRequest<any>): Observable<HttpEvent<any>> {
29+
let result: Observable<HttpEvent<any>>;
30+
if (this._isLocalRequest(req.url) || this._excludedService.skipSslPinning(req)) {
31+
result = super.handle(req);
32+
} else {
33+
result = this._request(req).pipe(
34+
map((response: HttpsResponse) => {
35+
if (response.statusCode < 200 || response.statusCode > 299) {
36+
throw this._mapHttpErrorResponse(response, req);
37+
}
38+
return new HttpResponse({
39+
body: response.content,
40+
headers: new HttpHeaders(response.headers),
41+
status: response.statusCode,
42+
statusText: response.reason,
43+
url: req.url
44+
});
45+
}),
46+
catchError((error) => throwError(() => error))
47+
);
48+
}
49+
50+
return result;
51+
}
52+
53+
private _isLocalRequest(url: string): boolean {
54+
return url.indexOf('~') === 0 || url.indexOf('/') === 0;
55+
}
56+
57+
private _request(request: HttpRequest<any>) {
58+
const method = request.method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD';
59+
return from(
60+
httpsRequest(
61+
{
62+
url: request.url,
63+
method,
64+
headers: this._mapHeaders(request),
65+
params: this._mapParams(request),
66+
body: request.body,
67+
timeout: this._defaults?.timeout ?? 3 * 60,
68+
allowLargeResponse: this._defaults?.allowLargeResponse ?? true,
69+
cachePolicy: this._defaults?.cachePolicy ?? 'noCache',
70+
cookiesEnabled: this._defaults?.cookiesEnabled ?? false
71+
},
72+
this._defaults?.useLegacy ?? true
73+
)
74+
);
75+
}
76+
77+
private _mapHeaders(request: HttpRequest<any>): Headers {
78+
const headerKeys = request.headers.keys();
79+
const headers = headerKeys.reduce<Headers>((accumulator, key) => {
80+
const values = request.headers.getAll(key);
81+
if (values !== null && values !== undefined) {
82+
accumulator[key] = values.length > 1 ? values.join(' ') : values[0];
83+
}
84+
return accumulator;
85+
}, {});
86+
87+
if (Object.keys(headers).length) {
88+
return headers;
89+
}
90+
91+
return {
92+
'Content-Type': 'application/json',
93+
Accept: 'application/json'
94+
};
95+
}
96+
97+
private _mapParams(request: HttpRequest<any>): HttpsRequestObject {
98+
const paramKeys = request.params.keys();
99+
const params = paramKeys.reduce<HttpsRequestObject>((accumulator, key) => {
100+
const values = request.params.getAll(key);
101+
if (values !== null && values !== undefined) {
102+
accumulator[key] = values.length > 1 ? values : values[0];
103+
}
104+
return accumulator;
105+
}, {});
106+
return params;
107+
}
108+
109+
private _mapHttpErrorResponse(error: HttpsResponse, request: HttpRequest<any>): HttpErrorResponse {
110+
return new HttpErrorResponse({
111+
error: error.content,
112+
status: error.statusCode,
113+
headers: new HttpHeaders(error.headers),
114+
statusText: error.reason || (typeof error.content === 'string' && error.content) || String(error.statusCode),
115+
url: request.url
116+
});
117+
}
118+
}

0 commit comments

Comments
 (0)