ijs.ext.http
Version:
IJavaScript extension for issuing and handling HTTP requests interactively.
197 lines (164 loc) • 5.59 kB
JavaScript
// Copyright 2015 Interactive Computing project (https://github.com/interactivecomputing).
// All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
// except in compliance with the License. You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the
// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
//
// request.js
// Implements request object.
//
var http = require('http'),
https = require('https'),
qs = require('querystring'),
url = require('url');
function Request(shell, transport, requestOptions, body, outputMode) {
this.shell = shell;
this.transport = transport;
this.requestOptions = requestOptions;
this.body = body;
this.outputMode = outputMode;
}
Request.prototype.execute = function() {
var self = this;
return self.shell.runtime.async(function(deferred) {
var request = self.transport.request(self.requestOptions, function(response) {
var status = 'HTTP ' + response.statusCode + ' ' + (response.statusMessage || '');
var statusDisplayed = false;
if ((self.outputMode == 'all') || (self.outputMode == 'status') ||
(self.outputMode == 'metadata')) {
statusDisplayed = true;
if ((response.statusCode >= 200) && (response.statusCode < 400)) {
console.log(status);
}
else {
console.error(status);
}
console.log();
}
if ((self.outputMode == 'all') || (self.outputMode == 'headers') ||
(self.outputMode == 'metadata')) {
for (var header in response.headers) {
console.log(header + ': ' + response.headers[header]);
}
console.log();
}
if (response.statusCode != 200) {
deferred.reject(statusDisplayed ? undefined : status);
return;
}
if ((self.outputMode == 'all') || (self.outputMode == 'body')) {
var buffers = [];
var totalLength = 0;
response.on('data', function(buffer) {
buffers.push(buffer);
totalLength += buffer.length;
});
response.on('end', function() {
var content = Buffer.concat(buffers, totalLength);
var contentType = response.headers['content-type'];
var mimeType = contentType.split(';')[0];
if ((contentType.indexOf('utf-8') > 0) ||
(contentType.indexOf('text/') == 0) ||
(mimeType == 'application/json')) {
content = content.toString('utf8');
if (mimeType == 'application/json') {
content = JSON.parse(content);
}
}
else {
content.mime = mimeType;
}
deferred.resolve(content);
});
}
else {
deferred.resolve(undefined);
}
});
request.on('error', function(e) {
deferred.reject(e);
});
if (self.body) {
request.write(self.body, 'utf8');
}
request.end();
});
}
Request.create = function(shell, args, data) {
var requestOptions = {
method: args.method.toUpperCase()
};
var urlData = url.parse(args.url, /* parseQuery */ true);
if (args.query) {
var queryData = shell.state[args.query];
if (queryData) {
for (var n in queryData) {
urlData.query[n] = queryData[n];
}
}
}
var query = qs.stringify(urlData.query);
if (args.headers) {
requestOptions.headers = shell.state[args.headers];
}
if (args.data) {
data = shell.state[args.data];
}
requestOptions.hostname = urlData.hostname;
requestOptions.port = urlData.port;
requestOptions.path = urlData.pathname;
if (query) {
requestOptions.path = requestOptions.path + '?' + query;
}
var transport = urlData.protocol == 'http:' ? http : https;
return new Request(shell, transport, requestOptions, data, args.response || 'all');
}
Request.parse = function(shell, args, data) {
var transport = http;
var requestOptions = {
headers: {}
};
var body;
data = data.split('\n');
// Determine verb and url from the first line
var firstLine = data[0].split(' ');
if (firstLine.length == 2) {
requestOptions.method = firstLine[0].toUpperCase();
var urlData = url.parse(firstLine[1]);
if (urlData.protocol == 'https:') {
transport = https;
}
requestOptions.hostname = urlData.hostname;
requestOptions.port = urlData.port;
requestOptions.path = urlData.path;
}
else {
throw shell.createError('Invalid request. Missing verb and/or URL to request.');
}
// Determine headers from subsequent lines until an empty line is found.
var i;
for (i = 1; i < data.length; i++) {
var line = data[i].trim();
if (!line) {
break;
}
var nameValue = line.split(':');
if (nameValue.length != 2) {
throw shell.createError('Invalid request. Invalid HTTP header.');
}
requestOptions.headers[nameValue[0].trim()] = nameValue[1].trim();
}
// Extract the body of the request
if ((i + 1) < data.length) {
body = data.slice(i + 1).join('\n');
requestOptions.headers['Content-Length'] = Buffer.byteLength(body, 'utf8');
}
return new Request(shell, transport, requestOptions, body, args.response || 'all');
}
module.exports = Request;