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

Commit 0fc3b75

Browse files
initial commit
0 parents  commit 0fc3b75

15 files changed

+6163
-0
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
_out
2+
node_modules
3+
.DS_Store
4+
testoutput.txt

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
Typed Rest Client for Node.js
2+
3+
Copyright (c) GitHub, Inc.
4+
5+
All rights reserved.
6+
7+
MIT License
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
10+
associated documentation files (the "Software"), to deal in the Software without restriction,
11+
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
12+
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
13+
subject to the following conditions:
14+
15+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
16+
17+
THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
18+
LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
19+
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

README.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
2+
# Typed HTTP Client with TypeScript Typings
3+
4+
A lightweight HTTP client optimized for use with actions, TypeScript with generics and async await.
5+
6+
## Features
7+
8+
- HTTP client with TypeScript generics and async/await/Promises
9+
- Typings included so no need to acquire separately (great for intellisense and no versioning drift)
10+
- Basic, Bearer and PAT Support out of the box. Extensible handlers for others.
11+
- Proxy support, just works with actions and the runner
12+
- Redirects supported
13+
14+
## Install
15+
16+
```
17+
npm install @actions/http-client --save
18+
```
19+
20+
## Samples
21+
22+
See the [HTTP](./__tests__) tests for detailed examples.
23+
24+
## Errors
25+
26+
### HTTP
27+
28+
The HTTP client does not throw unless truly exceptional.
29+
30+
* A request that successfully executes resulting in a 404, 500 etc... will return a response object with a status code and a body.
31+
* Redirects (3xx) will be followed by default.
32+
33+
See [HTTP tests](./__tests__) for detailed examples.
34+
35+
## Debugging
36+
37+
To enable detailed console logging of all HTTP requests and responses, set the NODE_DEBUG environment varible:
38+
39+
```
40+
export NODE_DEBUG=http
41+
```
42+
43+
or
44+
45+
```
46+
set NODE_DEBUG=http
47+
```
48+
49+
## Node support
50+
51+
The http-client is built using the latest LTS version of Node 12. We also support the latest LTS for Node 6, 8 and Node 10.
52+
53+
## Contributing
54+
55+
We welcome PRs. Please create an issue and if applicable, a design before proceeding with code.
56+
57+
To build:
58+
59+
```bash
60+
$ npm run build
61+
```
62+
63+
To run all tests:
64+
```bash
65+
$ npm test
66+
```

__tests__/auth.test.ts

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import * as httpm from '../_out';
2+
import * as path from 'path';
3+
import * as am from '../_out/auth';
4+
5+
describe('auth', () => {
6+
beforeEach(() => {
7+
8+
})
9+
10+
afterEach(() => {
11+
12+
})
13+
14+
it('does basic http get request with basic auth', async() => {
15+
let bh: am.BasicCredentialHandler = new am.BasicCredentialHandler('johndoe', 'password');
16+
let http: httpm.HttpClient = new httpm.HttpClient('http-client-tests', [bh]);
17+
let res: httpm.HttpClientResponse = await http.get('http://httpbin.org/get');
18+
expect(res.message.statusCode).toBe(200);
19+
let body: string = await res.readBody();
20+
let obj:any = JSON.parse(body);
21+
let auth: string = obj.headers.Authorization;
22+
let creds: string = Buffer.from(auth.substring('Basic '.length), 'base64').toString();
23+
expect(creds).toBe('johndoe:password');
24+
expect(obj.url).toBe("https://httpbin.org/get");
25+
});
26+
27+
it('does basic http get request with pat token auth', async() => {
28+
let token: string = 'scbfb44vxzku5l4xgc3qfazn3lpk4awflfryc76esaiq7aypcbhs';
29+
let ph: am.PersonalAccessTokenCredentialHandler =
30+
new am.PersonalAccessTokenCredentialHandler(token);
31+
32+
let http: httpm.HttpClient = new httpm.HttpClient('http-client-tests', [ph]);
33+
let res: httpm.HttpClientResponse = await http.get('http://httpbin.org/get');
34+
expect(res.message.statusCode).toBe(200);
35+
let body: string = await res.readBody();
36+
let obj:any = JSON.parse(body);
37+
let auth: string = obj.headers.Authorization;
38+
let creds: string = Buffer.from(auth.substring('Basic '.length), 'base64').toString();
39+
expect(creds).toBe('PAT:' + token);
40+
expect(obj.url).toBe("https://httpbin.org/get");
41+
});
42+
43+
it('does basic http get request with pat token auth', async() => {
44+
let token: string = 'scbfb44vxzku5l4xgc3qfazn3lpk4awflfryc76esaiq7aypcbhs';
45+
let ph: am.BearerCredentialHandler =
46+
new am.BearerCredentialHandler(token);
47+
48+
let http: httpm.HttpClient = new httpm.HttpClient('http-client-tests', [ph]);
49+
let res: httpm.HttpClientResponse = await http.get('http://httpbin.org/get');
50+
expect(res.message.statusCode).toBe(200);
51+
let body: string = await res.readBody();
52+
let obj:any = JSON.parse(body);
53+
let auth: string = obj.headers.Authorization;
54+
expect(auth).toBe('Bearer ' + token);
55+
expect(obj.url).toBe("https://httpbin.org/get");
56+
});
57+
})

__tests__/basics.test.ts

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
import * as httpm from '../_out';
2+
import * as path from 'path';
3+
import * as am from '../_out/auth';
4+
import * as fs from 'fs';
5+
6+
let sampleFilePath: string = path.join(__dirname, 'testoutput.txt');
7+
8+
describe('basics', () => {
9+
let _http: httpm.HttpClient;
10+
let _httpbin: httpm.HttpClient;
11+
12+
beforeEach(() => {
13+
_http = new httpm.HttpClient('http-client-tests');
14+
})
15+
16+
afterEach(() => {
17+
18+
})
19+
20+
it('constructs', () => {
21+
let http: httpm.HttpClient = new httpm.HttpClient('typed-test-client-tests');
22+
expect(http).toBeDefined();
23+
});
24+
25+
// responses from httpbin return something like:
26+
// {
27+
// "args": {},
28+
// "headers": {
29+
// "Connection": "close",
30+
// "Host": "httpbin.org",
31+
// "User-Agent": "typed-test-client-tests"
32+
// },
33+
// "origin": "173.95.152.44",
34+
// "url": "https://httpbin.org/get"
35+
// }
36+
37+
it('does basic http get request', async() => {
38+
let res: httpm.HttpClientResponse = await _http.get('http://httpbin.org/get');
39+
expect(res.message.statusCode).toBe(200);
40+
let body: string = await res.readBody();
41+
let obj: any = JSON.parse(body);
42+
expect(obj.url).toBe("https://httpbin.org/get");
43+
expect(obj.headers["User-Agent"]).toBeTruthy();
44+
});
45+
46+
it('does basic http get request with no user agent', async() => {
47+
let http: httpm.HttpClient = new httpm.HttpClient();
48+
let res: httpm.HttpClientResponse = await http.get('http://httpbin.org/get');
49+
expect(res.message.statusCode).toBe(200);
50+
let body: string = await res.readBody();
51+
let obj: any = JSON.parse(body);
52+
expect(obj.url).toBe("https://httpbin.org/get");
53+
expect(obj.headers["User-Agent"]).toBeFalsy();
54+
});
55+
56+
it('does basic https get request', async() => {
57+
let res: httpm.HttpClientResponse = await _http.get('https://httpbin.org/get');
58+
expect(res.message.statusCode).toBe(200);
59+
let body: string = await res.readBody();
60+
let obj: any = JSON.parse(body);
61+
expect(obj.url).toBe("https://httpbin.org/get");
62+
});
63+
64+
it('does basic http get request with default headers', async() => {
65+
let http: httpm.HttpClient = new httpm.HttpClient('http-client-tests', [], {
66+
headers: {
67+
'Accept': 'application/json',
68+
'Content-Type': 'application/json'
69+
}
70+
});
71+
let res: httpm.HttpClientResponse = await http.get('http://httpbin.org/get');
72+
expect(res.message.statusCode).toBe(200);
73+
let body: string = await res.readBody();
74+
let obj:any = JSON.parse(body);
75+
expect(obj.headers.Accept).toBe('application/json');
76+
expect(obj.headers['Content-Type']).toBe('application/json');
77+
expect(obj.url).toBe("https://httpbin.org/get");
78+
});
79+
80+
it('does basic http get request with merged headers', async() => {
81+
let http: httpm.HttpClient = new httpm.HttpClient('http-client-tests', [], {
82+
headers: {
83+
'Accept': 'application/json',
84+
'Content-Type': 'application/json'
85+
}
86+
});
87+
let res: httpm.HttpClientResponse = await http.get('http://httpbin.org/get', {
88+
'content-type': 'application/x-www-form-urlencoded'
89+
});
90+
expect(res.message.statusCode).toBe(200);
91+
let body: string = await res.readBody();
92+
let obj:any = JSON.parse(body);
93+
expect(obj.headers.Accept).toBe('application/json');
94+
expect(obj.headers['Content-Type']).toBe('application/x-www-form-urlencoded');
95+
expect(obj.url).toBe("https://httpbin.org/get");
96+
});
97+
98+
it('pipes a get request', () => {
99+
return new Promise<string>(async (resolve, reject) => {
100+
let file: NodeJS.WritableStream = fs.createWriteStream(sampleFilePath);
101+
(await _http.get('https://httpbin.org/get')).message.pipe(file).on('close', () => {
102+
let body: string = fs.readFileSync(sampleFilePath).toString();
103+
let obj:any = JSON.parse(body);
104+
expect(obj.url).toBe("https://httpbin.org/get");
105+
resolve();
106+
});
107+
});
108+
});
109+
110+
it('does basic get request with redirects', async() => {
111+
let res: httpm.HttpClientResponse = await _http.get("https://httpbin.org/redirect-to?url=" + encodeURIComponent("https://httpbin.org/get"))
112+
expect(res.message.statusCode).toBe(200);
113+
let body: string = await res.readBody();
114+
let obj:any = JSON.parse(body);
115+
expect(obj.url).toBe("https://httpbin.org/get");
116+
});
117+
118+
it('does basic get request with redirects (303)', async() => {
119+
let res: httpm.HttpClientResponse = await _http.get("https://httpbin.org/redirect-to?url=" + encodeURIComponent("https://httpbin.org/get") + '&status_code=303')
120+
expect(res.message.statusCode).toBe(200);
121+
let body: string = await res.readBody();
122+
let obj:any = JSON.parse(body);
123+
expect(obj.url).toBe("https://httpbin.org/get");
124+
});
125+
126+
it('returns 404 for not found get request on redirect', async() => {
127+
let res: httpm.HttpClientResponse = await _http.get("https://httpbin.org/redirect-to?url=" + encodeURIComponent("https://httpbin.org/status/404") + '&status_code=303')
128+
expect(res.message.statusCode).toBe(404);
129+
let body: string = await res.readBody();
130+
});
131+
132+
it('does not follow redirects if disabled', async() => {
133+
let http: httpm.HttpClient = new httpm.HttpClient('typed-test-client-tests', null, { allowRedirects: false });
134+
let res: httpm.HttpClientResponse = await http.get("https://httpbin.org/redirect-to?url=" + encodeURIComponent("https://httpbin.org/get"))
135+
expect(res.message.statusCode).toBe(302);
136+
let body: string = await res.readBody();
137+
});
138+
139+
it('does basic head request', async() => {
140+
let res: httpm.HttpClientResponse = await _http.head('http://httpbin.org/get');
141+
expect(res.message.statusCode).toBe(200);
142+
});
143+
144+
it('does basic http delete request', async() => {
145+
let res: httpm.HttpClientResponse = await _http.del('http://httpbin.org/delete');
146+
expect(res.message.statusCode).toBe(200);
147+
let body: string = await res.readBody();
148+
let obj:any = JSON.parse(body);
149+
});
150+
151+
it('does basic http post request', async() => {
152+
let b: string = 'Hello World!';
153+
let res: httpm.HttpClientResponse = await _http.post('http://httpbin.org/post', b);
154+
expect(res.message.statusCode).toBe(200);
155+
let body: string = await res.readBody();
156+
let obj:any = JSON.parse(body);
157+
expect(obj.data).toBe(b);
158+
expect(obj.url).toBe("https://httpbin.org/post");
159+
});
160+
161+
it('does basic http patch request', async() => {
162+
let b: string = 'Hello World!';
163+
let res: httpm.HttpClientResponse = await _http.patch('http://httpbin.org/patch', b);
164+
expect(res.message.statusCode).toBe(200);
165+
let body: string = await res.readBody();
166+
let obj:any = JSON.parse(body);
167+
expect(obj.data).toBe(b);
168+
expect(obj.url).toBe("https://httpbin.org/patch");
169+
});
170+
171+
it('does basic http options request', async() => {
172+
let res: httpm.HttpClientResponse = await _http.options('http://httpbin.org');
173+
expect(res.message.statusCode).toBe(200);
174+
let body: string = await res.readBody();
175+
});
176+
177+
it('returns 404 for not found get request', async() => {
178+
let res: httpm.HttpClientResponse = await _http.get('http://httpbin.org/status/404');
179+
expect(res.message.statusCode).toBe(404);
180+
let body: string = await res.readBody();
181+
});
182+
})

0 commit comments

Comments
 (0)