Skip to content
This repository was archived by the owner on May 29, 2025. It is now read-only.

Commit c947f39

Browse files
Create Paypalnods
1 parent 4cbb1e8 commit c947f39

File tree

1 file changed

+195
-0
lines changed

1 file changed

+195
-0
lines changed

Paypalnods

Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
'use strict';
2+
3+
let http = require('http');
4+
let https = require('https');
5+
let Buffer = require('buffer').Buffer;
6+
let url = require('url');
7+
let Encoder = require('./encoder').Encoder;
8+
let zlib = require('zlib');
9+
let Json = require('./serializer/json').Json;
10+
let Text = require('./serializer/text').Text;
11+
let Multipart = require('./serializer/multipart').Multipart;
12+
let FormEncoded = require('./serializer/form_encoded').FormEncoded;
13+
14+
const THIRTY_SECONDS = 10 * 3000;
15+
16+
class HttpError extends Error {
17+
constructor(response) {
18+
super();
19+
20+
this.message = response.message || response.text || 'An unknown error occured.';
21+
this.statusCode = response.statusCode;
22+
this.headers = response.headers;
23+
this._originalError = response;
24+
}
25+
}
26+
27+
class HttpClient {
28+
29+
constructor(environment) {
30+
this.environment = environment;
31+
this._injectors = [];
32+
this.encoder = new Encoder([new Json(), new Text(), new Multipart(), new FormEncoded()]);
33+
}
34+
35+
getUserAgent() {
36+
return 'PayPalHttp-Node HTTP/1.1';
37+
}
38+
39+
getTimeout() {
40+
return THIRTY_SECONDS;
41+
}
42+
43+
addInjector(injector) {
44+
if (typeof injector !== 'function' || injector.length !== 1) {
45+
throw new Error('injector must be a function that takes one argument');
46+
}
47+
48+
this._injectors.push(injector);
49+
}
50+
51+
formatHeaders(headers) {
52+
let formattedHeader = {};
53+
54+
Object.keys(headers).forEach(function (key) {
55+
if (key != null) {
56+
if (key.toLowerCase() === 'content-type') {
57+
formattedHeader[key.toLowerCase()] = headers[key].toLowerCase();
58+
} else {
59+
formattedHeader[key.toLowerCase()] = headers[key];
60+
}
61+
}
62+
});
63+
return formattedHeader;
64+
}
65+
66+
mapHeader(rawHeaders, formattedHeaders) {
67+
Object.keys(rawHeaders).forEach(function (key) {
68+
if (key != null) {
69+
let lCase = key.toLowerCase();
70+
71+
if (formattedHeaders[lCase] != null) {
72+
rawHeaders[key] = formattedHeaders[lCase];
73+
}
74+
}
75+
});
76+
return rawHeaders;
77+
}
78+
79+
execute(req) {
80+
let request = Object.assign({}, req);
81+
82+
if (!request.headers) {
83+
request.headers = {};
84+
}
85+
86+
let injectorPromises = this._injectors.map(function (injector) {
87+
return injector(request);
88+
});
89+
90+
let requestBody, requestAborted;
91+
let client = this.environment.baseUrl.startsWith('https') ? https : http;
92+
93+
let parsedUrl = url.parse(this.environment.baseUrl);
94+
95+
request.host = parsedUrl.hostname;
96+
request.port = parsedUrl.port;
97+
let formattedHeaders = this.formatHeaders(request.headers);
98+
99+
if (!formattedHeaders['user-agent'] || formattedHeaders['user-agent'] === 'Node') {
100+
request.headers['User-Agent'] = this.getUserAgent();
101+
}
102+
103+
if (request.body) {
104+
let rawHeaders = request.headers;
105+
106+
request.headers = formattedHeaders;
107+
requestBody = this.encoder.serializeRequest(request);
108+
request.headers = this.mapHeader(rawHeaders, formattedHeaders);
109+
request.headers['Content-Length'] = Buffer.byteLength(requestBody).toString();
110+
}
111+
112+
if (request.verb) {
113+
request.method = request.verb;
114+
}
115+
116+
return new Promise((resolve, reject) => {
117+
return Promise.all(injectorPromises).then(() => {
118+
let theRequest = client.request(request, (response) => {
119+
let buffers = [];
120+
121+
response.on('data', (responseBody) => {
122+
buffers.push(responseBody);
123+
});
124+
125+
response.on('end', () => {
126+
formattedHeaders = this.formatHeaders(response.headers);
127+
let contentEncoding = formattedHeaders['content-encoding'];
128+
129+
let body = Buffer.concat(buffers);
130+
131+
if (contentEncoding === 'gzip') {
132+
body = zlib.gunzipSync(body);
133+
}
134+
135+
body = body.toString('utf8');
136+
137+
if (response.statusCode >= 200 && response.statusCode <= 299) {
138+
resolve(this._parseResponse(body, response, formattedHeaders));
139+
} else {
140+
reject(new HttpError({
141+
text: body,
142+
statusCode: response.statusCode,
143+
headers: response.headers
144+
}));
145+
}
146+
});
147+
148+
response.on('error', reject);
149+
});
150+
151+
function timeoutHandler() {
152+
theRequest.abort();
153+
requestAborted = true;
154+
155+
reject(new Error('Request timed out'));
156+
}
157+
158+
theRequest.setTimeout(this.getTimeout(), timeoutHandler);
159+
160+
let requestSocket = null;
161+
162+
theRequest.on('socket', (socket) => {
163+
requestSocket = socket;
164+
});
165+
166+
theRequest.on('error', (error) => {
167+
if (requestAborted) { return; }
168+
requestSocket.removeListener('timeout', timeoutHandler);
169+
170+
reject(error);
171+
});
172+
173+
if (requestBody) {
174+
theRequest.write(requestBody);
175+
}
176+
theRequest.end();
177+
}).catch(reject);
178+
});
179+
}
180+
181+
_parseResponse(body, response, formattedHeaders) {
182+
var data = {
183+
statusCode: response.statusCode,
184+
headers: response.headers
185+
};
186+
187+
if (body) {
188+
data.result = this.encoder.deserializeResponse(body, formattedHeaders);
189+
}
190+
191+
return data;
192+
}
193+
}
194+
195+
module.exports = {HttpClient: HttpClient};

0 commit comments

Comments
 (0)