Your IP : 3.145.41.108
'use strict'
/**
* request.js
*
* Request class contains server only options
*/
const url = require('url')
const Headers = require('./headers.js')
const Body = require('./body.js')
const clone = Body.clone
const extractContentType = Body.extractContentType
const getTotalBytes = Body.getTotalBytes
const PARSED_URL = Symbol('url')
/**
* Request class
*
* @param Mixed input Url or Request instance
* @param Object init Custom options
* @return Void
*/
class Request {
constructor (input, init) {
if (!init) init = {}
let parsedURL
// normalize input
if (!(input instanceof Request)) {
if (input && input.href) {
// in order to support Node.js' Url objects; though WHATWG's URL objects
// will fall into this branch also (since their `toString()` will return
// `href` property anyway)
parsedURL = url.parse(input.href)
} else {
// coerce input to a string before attempting to parse
parsedURL = url.parse(`${input}`)
}
input = {}
} else {
parsedURL = url.parse(input.url)
}
let method = init.method || input.method || 'GET'
if ((init.body != null || (input instanceof Request && input.body !== null)) &&
(method === 'GET' || method === 'HEAD')) {
throw new TypeError('Request with GET/HEAD method cannot have body')
}
let inputBody = init.body != null
? init.body
: input instanceof Request && input.body !== null
? clone(input)
: null
Body.call(this, inputBody, {
timeout: init.timeout || input.timeout || 0,
size: init.size || input.size || 0
})
// fetch spec options
this.method = method.toUpperCase()
this.redirect = init.redirect || input.redirect || 'follow'
this.headers = new Headers(init.headers || input.headers || {})
if (init.body != null) {
const contentType = extractContentType(this)
if (contentType !== null && !this.headers.has('Content-Type')) {
this.headers.append('Content-Type', contentType)
}
}
// server only options
this.follow = init.follow !== undefined
? init.follow : input.follow !== undefined
? input.follow : 20
this.compress = init.compress !== undefined
? init.compress : input.compress !== undefined
? input.compress : true
this.counter = init.counter || input.counter || 0
this.agent = init.agent || input.agent
this[PARSED_URL] = parsedURL
Object.defineProperty(this, Symbol.toStringTag, {
value: 'Request',
writable: false,
enumerable: false,
configurable: true
})
}
get url () {
return url.format(this[PARSED_URL])
}
/**
* Clone this request
*
* @return Request
*/
clone () {
return new Request(this)
}
}
Body.mixIn(Request.prototype)
Object.defineProperty(Request.prototype, Symbol.toStringTag, {
value: 'RequestPrototype',
writable: false,
enumerable: false,
configurable: true
})
exports = module.exports = Request
exports.getNodeRequestOptions = function getNodeRequestOptions (request) {
const parsedURL = request[PARSED_URL]
const headers = new Headers(request.headers)
// fetch step 3
if (!headers.has('Accept')) {
headers.set('Accept', '*/*')
}
// Basic fetch
if (!parsedURL.protocol || !parsedURL.hostname) {
throw new TypeError('Only absolute URLs are supported')
}
if (!/^https?:$/.test(parsedURL.protocol)) {
throw new TypeError('Only HTTP(S) protocols are supported')
}
// HTTP-network-or-cache fetch steps 5-9
let contentLengthValue = null
if (request.body == null && /^(POST|PUT)$/i.test(request.method)) {
contentLengthValue = '0'
}
if (request.body != null) {
const totalBytes = getTotalBytes(request)
if (typeof totalBytes === 'number') {
contentLengthValue = String(totalBytes)
}
}
if (contentLengthValue) {
headers.set('Content-Length', contentLengthValue)
}
// HTTP-network-or-cache fetch step 12
if (!headers.has('User-Agent')) {
headers.set('User-Agent', 'node-fetch/1.0 (+https://github.com/bitinn/node-fetch)')
}
// HTTP-network-or-cache fetch step 16
if (request.compress) {
headers.set('Accept-Encoding', 'gzip,deflate')
}
if (!headers.has('Connection') && !request.agent) {
headers.set('Connection', 'close')
}
// HTTP-network fetch step 4
// chunked encoding is handled by Node.js
return Object.assign({}, parsedURL, {
method: request.method,
headers: headers.raw(),
agent: request.agent
})
}