UNPKG

7 kBJavaScriptView Raw
1var AWS = require('./core');
2var inherit = AWS.util.inherit;
3
4/**
5 * The endpoint that a service will talk to, for example,
6 * `'https://ec2.ap-southeast-1.amazonaws.com'`. If
7 * you need to override an endpoint for a service, you can
8 * set the endpoint on a service by passing the endpoint
9 * object with the `endpoint` option key:
10 *
11 * ```javascript
12 * var ep = new AWS.Endpoint('awsproxy.example.com');
13 * var s3 = new AWS.S3({endpoint: ep});
14 * s3.service.endpoint.hostname == 'awsproxy.example.com'
15 * ```
16 *
17 * Note that if you do not specify a protocol, the protocol will
18 * be selected based on your current {AWS.config} configuration.
19 *
20 * @!attribute protocol
21 * @return [String] the protocol (http or https) of the endpoint
22 * URL
23 * @!attribute hostname
24 * @return [String] the host portion of the endpoint, e.g.,
25 * example.com
26 * @!attribute host
27 * @return [String] the host portion of the endpoint including
28 * the port, e.g., example.com:80
29 * @!attribute port
30 * @return [Integer] the port of the endpoint
31 * @!attribute href
32 * @return [String] the full URL of the endpoint
33 */
34AWS.Endpoint = inherit({
35
36 /**
37 * @overload Endpoint(endpoint)
38 * Constructs a new endpoint given an endpoint URL. If the
39 * URL omits a protocol (http or https), the default protocol
40 * set in the global {AWS.config} will be used.
41 * @param endpoint [String] the URL to construct an endpoint from
42 */
43 constructor: function Endpoint(endpoint, config) {
44 AWS.util.hideProperties(this, ['slashes', 'auth', 'hash', 'search', 'query']);
45
46 if (typeof endpoint === 'undefined' || endpoint === null) {
47 throw new Error('Invalid endpoint: ' + endpoint);
48 } else if (typeof endpoint !== 'string') {
49 return AWS.util.copy(endpoint);
50 }
51
52 if (!endpoint.match(/^http/)) {
53 var useSSL = config && config.sslEnabled !== undefined ?
54 config.sslEnabled : AWS.config.sslEnabled;
55 endpoint = (useSSL ? 'https' : 'http') + '://' + endpoint;
56 }
57
58 AWS.util.update(this, AWS.util.urlParse(endpoint));
59
60 // Ensure the port property is set as an integer
61 if (this.port) {
62 this.port = parseInt(this.port, 10);
63 } else {
64 this.port = this.protocol === 'https:' ? 443 : 80;
65 }
66 }
67
68});
69
70/**
71 * The low level HTTP request object, encapsulating all HTTP header
72 * and body data sent by a service request.
73 *
74 * @!attribute method
75 * @return [String] the HTTP method of the request
76 * @!attribute path
77 * @return [String] the path portion of the URI, e.g.,
78 * "/list/?start=5&num=10"
79 * @!attribute headers
80 * @return [map<String,String>]
81 * a map of header keys and their respective values
82 * @!attribute body
83 * @return [String] the request body payload
84 * @!attribute endpoint
85 * @return [AWS.Endpoint] the endpoint for the request
86 * @!attribute region
87 * @api private
88 * @return [String] the region, for signing purposes only.
89 */
90AWS.HttpRequest = inherit({
91
92 /**
93 * @api private
94 */
95 constructor: function HttpRequest(endpoint, region) {
96 endpoint = new AWS.Endpoint(endpoint);
97 this.method = 'POST';
98 this.path = endpoint.path || '/';
99 this.headers = {};
100 this.body = '';
101 this.endpoint = endpoint;
102 this.region = region;
103 this._userAgent = '';
104 this.setUserAgent();
105 },
106
107 /**
108 * @api private
109 */
110 setUserAgent: function setUserAgent() {
111 this._userAgent = this.headers[this.getUserAgentHeaderName()] = AWS.util.userAgent();
112 },
113
114 getUserAgentHeaderName: function getUserAgentHeaderName() {
115 var prefix = AWS.util.isBrowser() ? 'X-Amz-' : '';
116 return prefix + 'User-Agent';
117 },
118
119 /**
120 * @api private
121 */
122 appendToUserAgent: function appendToUserAgent(agentPartial) {
123 if (typeof agentPartial === 'string' && agentPartial) {
124 this._userAgent += ' ' + agentPartial;
125 }
126 this.headers[this.getUserAgentHeaderName()] = this._userAgent;
127 },
128
129 /**
130 * @api private
131 */
132 getUserAgent: function getUserAgent() {
133 return this._userAgent;
134 },
135
136 /**
137 * @return [String] the part of the {path} excluding the
138 * query string
139 */
140 pathname: function pathname() {
141 return this.path.split('?', 1)[0];
142 },
143
144 /**
145 * @return [String] the query string portion of the {path}
146 */
147 search: function search() {
148 var query = this.path.split('?', 2)[1];
149 if (query) {
150 query = AWS.util.queryStringParse(query);
151 return AWS.util.queryParamsToString(query);
152 }
153 return '';
154 },
155
156 /**
157 * @api private
158 * update httpRequest endpoint with endpoint string
159 */
160 updateEndpoint: function updateEndpoint(endpointStr) {
161 var newEndpoint = new AWS.Endpoint(endpointStr);
162 this.endpoint = newEndpoint;
163 this.path = newEndpoint.path || '/';
164 }
165});
166
167/**
168 * The low level HTTP response object, encapsulating all HTTP header
169 * and body data returned from the request.
170 *
171 * @!attribute statusCode
172 * @return [Integer] the HTTP status code of the response (e.g., 200, 404)
173 * @!attribute headers
174 * @return [map<String,String>]
175 * a map of response header keys and their respective values
176 * @!attribute body
177 * @return [String] the response body payload
178 * @!attribute [r] streaming
179 * @return [Boolean] whether this response is being streamed at a low-level.
180 * Defaults to `false` (buffered reads). Do not modify this manually, use
181 * {createUnbufferedStream} to convert the stream to unbuffered mode
182 * instead.
183 */
184AWS.HttpResponse = inherit({
185
186 /**
187 * @api private
188 */
189 constructor: function HttpResponse() {
190 this.statusCode = undefined;
191 this.headers = {};
192 this.body = undefined;
193 this.streaming = false;
194 this.stream = null;
195 },
196
197 /**
198 * Disables buffering on the HTTP response and returns the stream for reading.
199 * @return [Stream, XMLHttpRequest, null] the underlying stream object.
200 * Use this object to directly read data off of the stream.
201 * @note This object is only available after the {AWS.Request~httpHeaders}
202 * event has fired. This method must be called prior to
203 * {AWS.Request~httpData}.
204 * @example Taking control of a stream
205 * request.on('httpHeaders', function(statusCode, headers) {
206 * if (statusCode < 300) {
207 * if (headers.etag === 'xyz') {
208 * // pipe the stream, disabling buffering
209 * var stream = this.response.httpResponse.createUnbufferedStream();
210 * stream.pipe(process.stdout);
211 * } else { // abort this request and set a better error message
212 * this.abort();
213 * this.response.error = new Error('Invalid ETag');
214 * }
215 * }
216 * }).send(console.log);
217 */
218 createUnbufferedStream: function createUnbufferedStream() {
219 this.streaming = true;
220 return this.stream;
221 }
222});
223
224
225AWS.HttpClient = inherit({});
226
227/**
228 * @api private
229 */
230AWS.HttpClient.getInstance = function getInstance() {
231 if (this.singleton === undefined) {
232 this.singleton = new this();
233 }
234 return this.singleton;
235};