delete internal http and rest client
This commit is contained in:
Родитель
d42dd40dc0
Коммит
b9cecf3e56
|
@ -1,8 +1,6 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
import restm = require('./RestClient');
|
||||
import httpm = require('./HttpClient');
|
||||
import vsom = require('./VsoClient');
|
||||
import VsoBaseInterfaces = require('./interfaces/common/VsoBaseInterfaces');
|
||||
import serm = require('./Serialization');
|
||||
|
@ -15,11 +13,6 @@ export class ClientApiBase {
|
|||
http: hm.HttpClient;
|
||||
rest: rm.RestClient;
|
||||
|
||||
// TODO: delete these three after regen
|
||||
httpClient: httpm.HttpCallbackClient;
|
||||
restCallbackClient: restm.RestCallbackClient;
|
||||
restClient: restm.RestClient;
|
||||
|
||||
vsoClient: vsom.VsoClient;
|
||||
|
||||
constructor(baseUrl: string, handlers: VsoBaseInterfaces.IRequestHandler[], userAgent?: string);
|
||||
|
@ -30,36 +23,12 @@ export class ClientApiBase {
|
|||
this.http = new hm.HttpClient(userAgent, handlers);
|
||||
this.rest = new rm.RestClient(userAgent, null, handlers);
|
||||
|
||||
// TODO: delete these three after regen
|
||||
this.httpClient = new httpm.HttpCallbackClient(userAgent, handlers);
|
||||
this.restCallbackClient = new restm.RestCallbackClient(this.httpClient);
|
||||
this.restClient = new restm.RestClient(userAgent, handlers);
|
||||
|
||||
this.vsoClient = new vsom.VsoClient(baseUrl, this.restCallbackClient);
|
||||
this.vsoClient = new vsom.VsoClient(baseUrl, this.rest);
|
||||
this.userAgent = userAgent;
|
||||
}
|
||||
|
||||
setUserAgent(userAgent: string) {
|
||||
this.userAgent = userAgent;
|
||||
this.httpClient.userAgent = userAgent;
|
||||
}
|
||||
|
||||
public connect(): Promise<any> {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.restCallbackClient.get(this.vsoClient.resolveUrl('/_apis/connectionData'), "", (err: any, statusCode: number, obj: any) => {
|
||||
if (err) {
|
||||
err.statusCode = statusCode;
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
resolve(obj);
|
||||
}
|
||||
}, null);
|
||||
});
|
||||
}
|
||||
|
||||
public createAcceptHeader(type: string, apiVersion?: string): string {
|
||||
return this.restCallbackClient.createAcceptHeader(type, apiVersion);
|
||||
return type + (apiVersion ? (';api-version=' + apiVersion) : '');
|
||||
}
|
||||
|
||||
public createRequestOptions(type: string, apiVersion?: string) {
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
import stream = require("stream");
|
||||
import * as restm from 'typed-rest-client/RestClient';
|
||||
import VsoBaseInterfaces = require('./interfaces/common/VsoBaseInterfaces');
|
||||
import FileContainerApiBase = require("./FileContainerApiBase");
|
||||
import FileContainerInterfaces = require("./interfaces/FileContainerInterfaces");
|
||||
|
@ -37,6 +38,7 @@ export class FileContainerApi extends FileContainerApiBase.FileContainerApiBase
|
|||
});
|
||||
}
|
||||
|
||||
// used by ChunkStream
|
||||
public _createItem(
|
||||
customHeaders: VsoBaseInterfaces.IHeaders,
|
||||
contentStream: NodeJS.ReadableStream,
|
||||
|
@ -56,15 +58,27 @@ export class FileContainerApi extends FileContainerApiBase.FileContainerApiBase
|
|||
};
|
||||
|
||||
customHeaders = customHeaders || {};
|
||||
customHeaders["Content-Type"] = "application/octet-stream";
|
||||
customHeaders["Content-Type"] = "";
|
||||
|
||||
|
||||
this.vsoClient.getVersioningData("2.2-preview.3", "Container", "e4f5c81e-e250-447b-9fef-bd48471bea5e", routeValues, queryValues)
|
||||
.then((versioningData: vsom.ClientVersioningData) => {
|
||||
var url: string = versioningData.requestUrl;
|
||||
var apiVersion: string = versioningData.apiVersion;
|
||||
var serializationData = { responseTypeMetadata: FileContainerInterfaces.TypeInfo.FileContainerItem, responseIsCollection: false };
|
||||
|
||||
this.restCallbackClient.uploadStream('PUT', url, apiVersion, contentStream, customHeaders, onResult, serializationData);
|
||||
let options: restm.IRequestOptions = this.createRequestOptions('application/octet-stream',
|
||||
versioningData.apiVersion);
|
||||
options.additionalHeaders = customHeaders;
|
||||
this.rest.uploadStream<FileContainerInterfaces.FileContainerItem>('PUT', url, contentStream, options)
|
||||
.then((res: restm.IRestResponse<FileContainerInterfaces.FileContainerItem>) => {
|
||||
let ret = this.formatResponse(res.result,
|
||||
FileContainerInterfaces.TypeInfo.FileContainerItem,
|
||||
false);
|
||||
onResult(null, res.statusCode, ret);
|
||||
})
|
||||
.catch((err) => {
|
||||
onResult(err, err.statusCode, null);
|
||||
});
|
||||
}, (error) => {
|
||||
onResult(error, error.statusCode, null);
|
||||
});
|
||||
|
|
|
@ -1,460 +0,0 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
import url = require("url");
|
||||
import http = require("http");
|
||||
import https = require("https");
|
||||
import tunnel = require("tunnel");
|
||||
import ifm = require('./interfaces/common/VsoBaseInterfaces');
|
||||
|
||||
http.globalAgent.maxSockets = 100;
|
||||
|
||||
export enum HttpCodes {
|
||||
OK = 200,
|
||||
MultipleChoices = 300,
|
||||
MovedPermanantly = 301,
|
||||
ResourceMoved = 302,
|
||||
NotModified = 304,
|
||||
UseProxy = 305,
|
||||
SwitchProxy = 306,
|
||||
TemporaryRedirect = 307,
|
||||
PermanentRedirect = 308,
|
||||
BadRequest = 400,
|
||||
Unauthorized = 401,
|
||||
PaymentRequired = 402,
|
||||
Forbidden = 403,
|
||||
NotFound = 404,
|
||||
MethodNotAllowed = 405,
|
||||
NotAcceptable = 406,
|
||||
ProxyAuthenticationRequired = 407,
|
||||
RequestTimeout = 408,
|
||||
Conflict = 409,
|
||||
Gone = 410,
|
||||
InternalServerError = 500,
|
||||
NotImplemented = 501,
|
||||
BadGateway = 502,
|
||||
ServiceUnavailable = 503,
|
||||
GatewayTimeout = 504,
|
||||
}
|
||||
|
||||
export class HttpClientResponse {
|
||||
constructor(message: http.IncomingMessage) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public message: http.IncomingMessage;
|
||||
readBody(): Promise<string> {
|
||||
return new Promise<string>(async(resolve, reject) => {
|
||||
let output: string = '';
|
||||
|
||||
this.message.on('data', (chunk: string) => {
|
||||
output += chunk;
|
||||
});
|
||||
|
||||
this.message.on('end', () => {
|
||||
resolve(output);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export interface RequestInfo {
|
||||
options: http.RequestOptions;
|
||||
parsedUrl: url.Url;
|
||||
httpModule: any;
|
||||
}
|
||||
|
||||
export function isHttps(requestUrl: string) {
|
||||
let parsedUrl: url.Url = url.parse(requestUrl);
|
||||
return parsedUrl.protocol === 'https:';
|
||||
}
|
||||
|
||||
export class HttpClient {
|
||||
userAgent: string;
|
||||
handlers: ifm.IRequestHandler[];
|
||||
socketTimeout: number;
|
||||
|
||||
constructor(userAgent: string, handlers?: ifm.IRequestHandler[], socketTimeout?: number) {
|
||||
this.userAgent = userAgent;
|
||||
this.handlers = handlers;
|
||||
this.socketTimeout = socketTimeout ? socketTimeout : 3 * 60000;
|
||||
}
|
||||
|
||||
public get(requestUrl: string, additionalHeaders?: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return this.request('GET', requestUrl, null, additionalHeaders || {});
|
||||
}
|
||||
|
||||
public del(requestUrl: string, additionalHeaders?: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return this.request('DELETE', requestUrl, null, additionalHeaders || {});
|
||||
}
|
||||
|
||||
public post(requestUrl: string, data: string, additionalHeaders?: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return this.request('POST', requestUrl, data, additionalHeaders || {});
|
||||
}
|
||||
|
||||
public patch(requestUrl: string, data: string, additionalHeaders?: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return this.request('PATCH', requestUrl, data, additionalHeaders || {});
|
||||
}
|
||||
|
||||
public put(requestUrl: string, data: string, additionalHeaders?: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return this.request('PUT', requestUrl, data, additionalHeaders || {});
|
||||
}
|
||||
|
||||
public sendStream(verb: string, requestUrl: string, stream: NodeJS.ReadableStream, additionalHeaders?: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return this.request(verb, requestUrl, stream, additionalHeaders);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a raw http request.
|
||||
* All other methods such as get, post, patch, and request ultimately call this.
|
||||
* Prefer get, del, post and patch
|
||||
*/
|
||||
public request(verb: string, requestUrl: string, data: string | NodeJS.ReadableStream, headers: ifm.IHeaders): Promise<HttpClientResponse> {
|
||||
return new Promise<HttpClientResponse>(async(resolve, reject) => {
|
||||
try {
|
||||
var info: RequestInfo = this._prepareRequest(verb, requestUrl, headers);
|
||||
let res: HttpClientResponse = await this._requestRaw(info, data);
|
||||
|
||||
// TODO: check 401 if handled
|
||||
|
||||
// TODO: retry support
|
||||
|
||||
resolve(res);
|
||||
}
|
||||
catch (err) {
|
||||
// only throws in truly exceptional cases (connection, can't resolve etc...)
|
||||
// responses from the server do not throw
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _requestRaw(info: RequestInfo, data: string | NodeJS.ReadableStream): Promise<HttpClientResponse> {
|
||||
return new Promise<HttpClientResponse>((resolve, reject) => {
|
||||
let socket;
|
||||
|
||||
let isDataString = typeof(data) === 'string';
|
||||
|
||||
if (typeof(data) === 'string') {
|
||||
info.options.headers["Content-Length"] = Buffer.byteLength(data, 'utf8');
|
||||
}
|
||||
|
||||
let req: http.ClientRequest = info.httpModule.request(info.options, (msg: http.IncomingMessage) => {
|
||||
let res: HttpClientResponse = new HttpClientResponse(msg);
|
||||
resolve(res);
|
||||
});
|
||||
|
||||
req.on('socket', (sock) => {
|
||||
socket = sock;
|
||||
});
|
||||
|
||||
// If we ever get disconnected, we want the socket to timeout eventually
|
||||
req.setTimeout(this.socketTimeout, () => {
|
||||
if (socket) {
|
||||
socket.end();
|
||||
}
|
||||
reject(new Error('Request timeout: ' + info.options.path));
|
||||
});
|
||||
|
||||
req.on('error', function (err) {
|
||||
// err has statusCode property
|
||||
// res should have headers
|
||||
reject(err);
|
||||
});
|
||||
|
||||
if (data && typeof(data) === 'string') {
|
||||
req.write(data, 'utf8');
|
||||
}
|
||||
|
||||
if (data && typeof(data) !== 'string') {
|
||||
data.on('close', function () {
|
||||
req.end();
|
||||
});
|
||||
|
||||
data.pipe(req);
|
||||
}
|
||||
else {
|
||||
req.end();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private _prepareRequest(method: string, requestUrl: string, headers: any): RequestInfo {
|
||||
let info: RequestInfo = <RequestInfo>{};
|
||||
|
||||
info.parsedUrl = url.parse(requestUrl);
|
||||
let usingSsl = info.parsedUrl.protocol === 'https:';
|
||||
info.httpModule = usingSsl ? https : http;
|
||||
var defaultPort: number = usingSsl ? 443 : 80;
|
||||
|
||||
var proxyUrl: url.Url;
|
||||
if (process.env.HTTPS_PROXY && usingSsl) {
|
||||
proxyUrl = url.parse(process.env.HTTPS_PROXY);
|
||||
} else if (process.env.HTTP_PROXY) {
|
||||
proxyUrl = url.parse(process.env.HTTP_PROXY);
|
||||
}
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||
info.options = <http.RequestOptions>{};
|
||||
info.options.host = info.parsedUrl.hostname;
|
||||
info.options.port = info.parsedUrl.port ? parseInt(info.parsedUrl.port) : defaultPort;
|
||||
info.options.path = (info.parsedUrl.pathname || '') + (info.parsedUrl.search || '');
|
||||
info.options.method = method;
|
||||
info.options.headers = headers || {};
|
||||
info.options.headers["User-Agent"] = this.userAgent;
|
||||
|
||||
let useProxy = proxyUrl && proxyUrl.hostname;
|
||||
if (useProxy) {
|
||||
var agentOptions: tunnel.TunnelOptions = {
|
||||
maxSockets: http.globalAgent.maxSockets,
|
||||
proxy: {
|
||||
// TODO: support proxy-authorization
|
||||
//proxyAuth: "user:password",
|
||||
host: proxyUrl.hostname,
|
||||
port: proxyUrl.port
|
||||
}
|
||||
};
|
||||
|
||||
var tunnelAgent: Function;
|
||||
var overHttps = proxyUrl.protocol === 'https:';
|
||||
if (usingSsl) {
|
||||
tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp;
|
||||
} else {
|
||||
tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp;
|
||||
}
|
||||
|
||||
info.options.agent = tunnelAgent(agentOptions);
|
||||
}
|
||||
|
||||
// gives handlers an opportunity to participate
|
||||
if (this.handlers) {
|
||||
this.handlers.forEach((handler) => {
|
||||
handler.prepareRequest(info.options);
|
||||
});
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Legacy callback client. Will delete.
|
||||
//
|
||||
export class HttpCallbackClient {
|
||||
userAgent: string;
|
||||
handlers: ifm.IRequestHandler[];
|
||||
socketTimeout: number;
|
||||
isSsl: boolean;
|
||||
|
||||
constructor(userAgent: string, handlers?: ifm.IRequestHandler[], socketTimeout?: number) {
|
||||
this.userAgent = userAgent;
|
||||
this.handlers = handlers;
|
||||
this.socketTimeout = socketTimeout ? socketTimeout : 3 * 60000;
|
||||
}
|
||||
|
||||
get(verb: string, requestUrl: string, headers: ifm.IHeaders, onResult: (err: any, res: http.IncomingMessage, contents: string) => void): void {
|
||||
var options = this._getOptions(verb, requestUrl, headers);
|
||||
this.request(options.protocol, options.options, null, onResult);
|
||||
}
|
||||
|
||||
// POST, PATCH, PUT
|
||||
send(verb: string, requestUrl: string, data: string, headers: ifm.IHeaders, onResult: (err: any, res: http.IncomingMessage, contents: string) => void): void {
|
||||
var options = this._getOptions(verb, requestUrl, headers);
|
||||
this.request(options.protocol, options.options, data, onResult);
|
||||
}
|
||||
|
||||
sendStream(verb: string, requestUrl: string, stream: NodeJS.ReadableStream, headers: ifm.IHeaders, onResult: (err: any, res: http.IncomingMessage, contents: string) => void): void {
|
||||
var options = this._getOptions(verb, requestUrl, headers);
|
||||
|
||||
var req = options.protocol.request(options.options, (res) => {
|
||||
let output: string = '';
|
||||
|
||||
res.on('data', function (chunk) {
|
||||
output += chunk;
|
||||
});
|
||||
|
||||
res.on('end', function () {
|
||||
// res has statusCode and headers
|
||||
onResult(null, res, output);
|
||||
});
|
||||
});
|
||||
|
||||
req.on('error', function (err) {
|
||||
// err has statusCode property
|
||||
// res should have headers
|
||||
onResult(err, null, null);
|
||||
});
|
||||
|
||||
stream.on('close', function () {
|
||||
req.end();
|
||||
});
|
||||
|
||||
stream.pipe(req);
|
||||
}
|
||||
|
||||
getStream(requestUrl: string, accept: string, onResult: (err: any, statusCode: number, res: NodeJS.ReadableStream) => void): void {
|
||||
let headers = {};
|
||||
headers['ACCEPT'] = accept;
|
||||
var options = this._getOptions('GET', requestUrl, headers);
|
||||
|
||||
var req = options.protocol.request(options.options, (res: http.IncomingMessage) => {
|
||||
onResult(null, res.statusCode, res);
|
||||
});
|
||||
|
||||
req.on('error', (err) => {
|
||||
onResult(err, err.statusCode, null);
|
||||
});
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes an http request delegating authentication to handlers.
|
||||
* returns http result as contents buffer
|
||||
* All other methods such as get, post, and patch ultimately call this.
|
||||
*/
|
||||
request(protocol: any, options: any, data: string, onResult: (err: any, res: http.IncomingMessage, contents: string) => void): void {
|
||||
// Set up a callback to pass off 401s to an authentication handler that can deal with it
|
||||
var callback = (err: any, res: http.ClientResponse, contents: string) => {
|
||||
var authHandler;
|
||||
if (this.handlers) {
|
||||
this.handlers.some(function (handler, index, handlers) {
|
||||
// Find the first one that can handle the auth based on the response
|
||||
if (handler.canHandleAuthentication(res)) {
|
||||
authHandler = handler;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
if (authHandler !== undefined) {
|
||||
authHandler.handleAuthentication(this, protocol, options, data, onResult);
|
||||
} else {
|
||||
// No auth handler found, call onResult normally
|
||||
onResult(err, res, contents);
|
||||
}
|
||||
};
|
||||
|
||||
this.requestRaw(protocol, options, data, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a raw http request.
|
||||
* All other methods such as get, post, patch, and request ultimately call this.
|
||||
*/
|
||||
requestRaw(protocol: any, options: any, data: string, onResult: (err: any, res: http.IncomingMessage, contents: string) => void): void {
|
||||
var socket;
|
||||
|
||||
if (data) {
|
||||
options.headers["Content-Length"] = Buffer.byteLength(data, 'utf8');
|
||||
}
|
||||
|
||||
var callbackCalled: boolean = false;
|
||||
var handleResult = (err: any, res: http.IncomingMessage, contents: string) => {
|
||||
if (!callbackCalled) {
|
||||
callbackCalled = true;
|
||||
onResult(err, res, contents);
|
||||
}
|
||||
};
|
||||
|
||||
var req = protocol.request(options, (res) => {
|
||||
let output: string = '';
|
||||
res.setEncoding('utf8');
|
||||
|
||||
res.on('data', (chunk: string) => {
|
||||
output += chunk;
|
||||
});
|
||||
|
||||
res.on('end', () => {
|
||||
// res has statusCode and headers
|
||||
handleResult(null, res, output);
|
||||
});
|
||||
});
|
||||
|
||||
req.on('socket', (sock) => {
|
||||
socket = sock;
|
||||
});
|
||||
|
||||
// If we ever get disconnected, we want the socket to timeout eventually
|
||||
req.setTimeout(this.socketTimeout, function() {
|
||||
if (socket) {
|
||||
socket.end();
|
||||
}
|
||||
handleResult(new Error('Request timeout: ' + options.path), null, null);
|
||||
});
|
||||
|
||||
req.on('error', function (err) {
|
||||
// err has statusCode property
|
||||
// res should have headers
|
||||
handleResult(err, null, null);
|
||||
});
|
||||
|
||||
if (data) {
|
||||
req.write(data, 'utf8');
|
||||
}
|
||||
|
||||
req.end();
|
||||
}
|
||||
|
||||
private _getOptions(method: string, requestUrl: string, headers: any): any {
|
||||
|
||||
var parsedUrl: url.Url = url.parse(requestUrl);
|
||||
var usingSsl = parsedUrl.protocol === 'https:';
|
||||
var prot: any = usingSsl ? https : http;
|
||||
var defaultPort = usingSsl ? 443 : 80;
|
||||
this.isSsl = usingSsl;
|
||||
|
||||
var proxyUrl: url.Url;
|
||||
if (process.env.HTTPS_PROXY && usingSsl) {
|
||||
proxyUrl = url.parse(process.env.HTTPS_PROXY);
|
||||
} else if (process.env.HTTP_PROXY) {
|
||||
proxyUrl = url.parse(process.env.HTTP_PROXY);
|
||||
}
|
||||
|
||||
process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
|
||||
var options: any = {
|
||||
host: parsedUrl.hostname,
|
||||
port: parsedUrl.port || defaultPort,
|
||||
path: (parsedUrl.pathname || '') + (parsedUrl.search || ''),
|
||||
method: method,
|
||||
headers: headers || {}
|
||||
};
|
||||
|
||||
options.headers["User-Agent"] = this.userAgent;
|
||||
|
||||
var useProxy = proxyUrl && proxyUrl.hostname;
|
||||
if (useProxy) {
|
||||
var agentOptions: tunnel.TunnelOptions = {
|
||||
maxSockets: http.globalAgent.maxSockets,
|
||||
proxy: {
|
||||
// TODO: support proxy-authorization
|
||||
//proxyAuth: "user:password",
|
||||
host: proxyUrl.hostname,
|
||||
port: proxyUrl.port
|
||||
}
|
||||
};
|
||||
|
||||
var tunnelAgent: Function;
|
||||
var overHttps = proxyUrl.protocol === 'https:';
|
||||
if (usingSsl) {
|
||||
tunnelAgent = overHttps ? tunnel.httpsOverHttps : tunnel.httpsOverHttp;
|
||||
} else {
|
||||
tunnelAgent = overHttps ? tunnel.httpOverHttps : tunnel.httpOverHttp;
|
||||
}
|
||||
|
||||
options.agent = tunnelAgent(agentOptions);
|
||||
}
|
||||
|
||||
if (this.handlers) {
|
||||
this.handlers.forEach((handler) => {
|
||||
handler.prepareRequest(options);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
protocol: prot,
|
||||
options: options,
|
||||
};
|
||||
}
|
||||
}
|
|
@ -1,314 +0,0 @@
|
|||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
||||
|
||||
import fs = require("fs");
|
||||
import http = require("http");
|
||||
import httpm = require('./HttpClient');
|
||||
import ifm = require("./interfaces/common/VsoBaseInterfaces");
|
||||
import serm = require('./Serialization');
|
||||
|
||||
export interface IRestClientResponse {
|
||||
statusCode: number,
|
||||
result: any
|
||||
}
|
||||
|
||||
export class RestClient {
|
||||
client: httpm.HttpClient;
|
||||
versionParam: string;
|
||||
|
||||
constructor(userAgent: string, handlers?: ifm.IRequestHandler[], socketTimeout?: number, versionParam?: string) {
|
||||
// TODO: should we really do this?
|
||||
this.versionParam = versionParam || 'api-version';
|
||||
this.client = new httpm.HttpClient(userAgent, handlers, socketTimeout);
|
||||
}
|
||||
|
||||
public async get(requestUrl: string,
|
||||
apiVersion: string,
|
||||
additionalHeaders?: ifm.IHeaders): Promise<IRestClientResponse> {
|
||||
|
||||
var headers = additionalHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
|
||||
let res: httpm.HttpClientResponse = await this.client.get(requestUrl, headers);
|
||||
return this._processResponse(res);
|
||||
}
|
||||
|
||||
public async del(requestUrl: string,
|
||||
apiVersion: string,
|
||||
additionalHeaders?: ifm.IHeaders): Promise<IRestClientResponse> {
|
||||
|
||||
var headers = additionalHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
|
||||
let res: httpm.HttpClientResponse = await this.client.del(requestUrl, headers);
|
||||
return this._processResponse(res);
|
||||
}
|
||||
|
||||
public async create(requestUrl: string,
|
||||
apiVersion: string,
|
||||
resources: any,
|
||||
additionalHeaders?: ifm.IHeaders): Promise<IRestClientResponse> {
|
||||
|
||||
var headers = additionalHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
headers["Content-Type"] = headers["Content-Type"] || 'application/json; charset=utf-8';
|
||||
|
||||
let data: string = JSON.stringify(resources, null, 2);
|
||||
let res: httpm.HttpClientResponse = await this.client.post(requestUrl, data, headers);
|
||||
return this._processResponse(res);
|
||||
}
|
||||
|
||||
public async update(requestUrl: string,
|
||||
apiVersion: string,
|
||||
resources: any,
|
||||
additionalHeaders?: ifm.IHeaders): Promise<IRestClientResponse> {
|
||||
|
||||
var headers = additionalHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
headers["Content-Type"] = headers["Content-Type"] || 'application/json; charset=utf-8';
|
||||
|
||||
let data: string = JSON.stringify(resources, null, 2);
|
||||
let res: httpm.HttpClientResponse = await this.client.patch(requestUrl, data, headers);
|
||||
return this._processResponse(res);
|
||||
}
|
||||
|
||||
public async replace(requestUrl: string,
|
||||
apiVersion: string,
|
||||
resources: any,
|
||||
additionalHeaders?: ifm.IHeaders): Promise<IRestClientResponse> {
|
||||
|
||||
var headers = additionalHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
headers["Content-Type"] = headers["Content-Type"] || 'application/json; charset=utf-8';
|
||||
|
||||
let data: string = JSON.stringify(resources, null, 2);
|
||||
let res: httpm.HttpClientResponse = await this.client.put(requestUrl, data, headers);
|
||||
return this._processResponse(res);
|
||||
}
|
||||
|
||||
public async uploadStream(verb: string, requestUrl: string, apiVersion: string, stream: NodeJS.ReadableStream, additionalHeaders: ifm.IHeaders): Promise<IRestClientResponse> {
|
||||
var headers = additionalHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
|
||||
let res: httpm.HttpClientResponse = await this.client.sendStream(verb, requestUrl, stream, headers);
|
||||
return this._processResponse(res);
|
||||
}
|
||||
|
||||
public createAcceptHeader(type: string, apiVersion?: string): string {
|
||||
return type + (apiVersion ? (';' + this.versionParam + '=' + apiVersion) : '');
|
||||
}
|
||||
|
||||
private async _processResponse(res: httpm.HttpClientResponse): Promise<IRestClientResponse> {
|
||||
return new Promise<IRestClientResponse>(async(resolve, reject) => {
|
||||
let rres: IRestClientResponse = <IRestClientResponse>{};
|
||||
let statusCode: number = res.message.statusCode;
|
||||
rres.statusCode = statusCode;
|
||||
|
||||
// not found leads to null obj returned
|
||||
if (statusCode == httpm.HttpCodes.NotFound) {
|
||||
resolve(rres);
|
||||
}
|
||||
|
||||
let obj: any;
|
||||
|
||||
// get the result from the body
|
||||
try {
|
||||
let contents: string = await res.readBody();
|
||||
if (contents && contents.length > 0) {
|
||||
obj = JSON.parse(contents);
|
||||
rres.result = obj;
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
reject(new Error('Invalid Resource'));
|
||||
}
|
||||
|
||||
if (statusCode > 299) {
|
||||
let msg: string;
|
||||
|
||||
// if exception/error in body, attempt to get better error
|
||||
if (obj && obj.message) {
|
||||
msg = obj.message;
|
||||
} else {
|
||||
msg = "Failed request: (" + statusCode + ") " + res.message.url;
|
||||
}
|
||||
|
||||
reject(new Error(msg));
|
||||
} else {
|
||||
resolve(rres);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class RestCallbackClient {
|
||||
baseUrl: string;
|
||||
basePath: string;
|
||||
httpClient: httpm.HttpCallbackClient;
|
||||
versionParam: string;
|
||||
|
||||
constructor(httpClient: httpm.HttpCallbackClient, versionParam?: string) {
|
||||
versionParam = versionParam || 'api-version';
|
||||
this.httpClient = httpClient;
|
||||
this.versionParam = versionParam;
|
||||
}
|
||||
|
||||
get(url: string, apiVersion: string, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void): void {
|
||||
this._getJson('GET', url, apiVersion, customHeaders, onResult);
|
||||
}
|
||||
|
||||
del(url: string, apiVersion: string, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void): void {
|
||||
this._getJson('DELETE', url, apiVersion, customHeaders, onResult);
|
||||
}
|
||||
|
||||
create(url: string, apiVersion: string, resources: any, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void, serializationData?: serm.SerializationData): void {
|
||||
var headers = customHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
headers["Content-Type"] = headers["Content-Type"] || 'application/json; charset=utf-8';
|
||||
this._sendJson('POST', url, apiVersion, resources, customHeaders, onResult);
|
||||
}
|
||||
|
||||
update(url: string, apiVersion: string, resources: any, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void, serializationData?: serm.SerializationData): void {
|
||||
this._sendJson('PATCH', url, apiVersion, resources, customHeaders, onResult);
|
||||
}
|
||||
|
||||
options(url: string, onResult: (err: any, statusCode: number, obj: any) => void): void {
|
||||
this._getJson('OPTIONS', url, "", null, onResult);
|
||||
}
|
||||
|
||||
uploadFile(verb: string, url: string, apiVersion: string, filePath: string, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void, serializationData?: serm.SerializationData): void {
|
||||
fs.stat(filePath, (err, stats) => {
|
||||
if (err) {
|
||||
onResult(err, 400, null);
|
||||
return;
|
||||
}
|
||||
|
||||
var headers = customHeaders || {};
|
||||
headers["Content-Length"] = stats.size;
|
||||
|
||||
var contentStream: NodeJS.ReadableStream = fs.createReadStream(filePath);
|
||||
|
||||
this.uploadStream(verb, url, apiVersion, contentStream, headers, onResult, serializationData);
|
||||
});
|
||||
}
|
||||
|
||||
uploadStream(verb: string, url: string, apiVersion: string, contentStream: NodeJS.ReadableStream, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void, serializationData?: serm.SerializationData): void {
|
||||
var headers = customHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
|
||||
this.httpClient.sendStream(verb, url, contentStream, headers, (err: any, res: ifm.IHttpResponse, contents: string) => {
|
||||
if (err) {
|
||||
onResult(err, err.statusCode, contents);
|
||||
return;
|
||||
}
|
||||
|
||||
_processResponse(url, res, contents, onResult);
|
||||
});
|
||||
}
|
||||
|
||||
replace(url: string, apiVersion: string, resources: any, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void): void {
|
||||
this._sendJson('PUT', url, apiVersion, resources, customHeaders, onResult);
|
||||
}
|
||||
|
||||
_getJson(verb: string, url: string, apiVersion: string, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void): void {
|
||||
|
||||
var headers = {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
this.httpClient.get(verb, url, headers, (err: any, res: ifm.IHttpResponse, contents: string) => {
|
||||
if (err) {
|
||||
onResult(err, err.statusCode, null);
|
||||
return;
|
||||
}
|
||||
|
||||
_processResponse(url, res, contents, onResult);
|
||||
});
|
||||
}
|
||||
|
||||
_sendJson(verb: string, url: string, apiVersion: string, resources: any, customHeaders: ifm.IHeaders, onResult: (err: any, statusCode: number, obj: any) => void): void {
|
||||
if (!resources) {
|
||||
throw new Error('invalid resource');
|
||||
}
|
||||
|
||||
var headers = customHeaders || {};
|
||||
headers["Accept"] = this.createAcceptHeader('application/json', apiVersion);
|
||||
headers["Content-Type"] = headers["Content-Type"] || 'application/json; charset=utf-8';
|
||||
|
||||
let data: string;
|
||||
|
||||
data = JSON.stringify(resources, null, 2);
|
||||
|
||||
this.httpClient.send(verb, url, data, headers, (err: any, res: ifm.IHttpResponse, contents: string) => {
|
||||
if (err) {
|
||||
onResult(err, err.statusCode, null);
|
||||
return;
|
||||
}
|
||||
|
||||
_processResponse(url, res, contents, onResult);
|
||||
});
|
||||
}
|
||||
|
||||
public createAcceptHeader(type: string, apiVersion?: string): string {
|
||||
return type + (apiVersion ? (';' + this.versionParam + '=' + apiVersion) : '');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var httpCodes = {
|
||||
300: "Multiple Choices",
|
||||
301: "Moved Permanantly",
|
||||
302: "Resource Moved",
|
||||
304: "Not Modified",
|
||||
305: "Use Proxy",
|
||||
306: "Switch Proxy",
|
||||
307: "Temporary Redirect",
|
||||
308: "Permanent Redirect",
|
||||
400: "Bad Request",
|
||||
401: "Unauthorized",
|
||||
402: "Payment Required",
|
||||
403: "Forbidden",
|
||||
404: "Not Found",
|
||||
405: "Method Not Allowed",
|
||||
406: "Not Acceptable",
|
||||
407: "Proxy Authentication Required",
|
||||
408: "Request Timeout",
|
||||
409: "Conflict",
|
||||
410: "Gone",
|
||||
500: "Internal Server Error",
|
||||
501: "Not Implemented",
|
||||
502: "Bad Gateway",
|
||||
503: "Service Unavailable",
|
||||
504: "Gateway Timeout"
|
||||
}
|
||||
|
||||
function _processResponse(url: string,
|
||||
res: ifm.IHttpResponse,
|
||||
contents: string,
|
||||
onResult: (err: any, statusCode: number, obj: any) => void) {
|
||||
let jsonObj: any;
|
||||
|
||||
if (contents && contents.length > 0) {
|
||||
try {
|
||||
jsonObj = JSON.parse(contents);
|
||||
} catch (e) {
|
||||
onResult(new Error('Invalid Resource'), res.statusCode, null);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (res.statusCode > 299) {
|
||||
// default error message
|
||||
var msg = httpCodes[res.statusCode] ? "Failed Request: " + httpCodes[res.statusCode] : "Failed Request";
|
||||
msg += '(' + res.statusCode + ') - ';
|
||||
|
||||
// if exception/error in body, attempt to get better error
|
||||
if (jsonObj && jsonObj.message) {
|
||||
msg += jsonObj.message;
|
||||
} else {
|
||||
msg += url;
|
||||
}
|
||||
|
||||
onResult(new Error(msg), res.statusCode, null);
|
||||
} else {
|
||||
onResult(null, res.statusCode, jsonObj);
|
||||
}
|
||||
};
|
|
@ -5,6 +5,7 @@ import url = require('url');
|
|||
import vsom = require('./VsoClient');
|
||||
import TaskAgentInterfaces = require("./interfaces/TaskAgentInterfaces");
|
||||
import VsoBaseInterfaces = require('./interfaces/common/VsoBaseInterfaces');
|
||||
import * as restm from 'typed-rest-client/RestClient';
|
||||
|
||||
export interface ITaskAgentApi extends taskagentbasem.ITaskAgentApiBase {
|
||||
uploadTaskDefinition(customHeaders: VsoBaseInterfaces.IHeaders, contentStream: NodeJS.ReadableStream, taskId: string, overwrite: boolean) : Promise<void>;
|
||||
|
@ -167,43 +168,7 @@ export class TaskAgentApi extends taskagentbasem.TaskAgentApiBase implements ITa
|
|||
* @param {boolean} overwrite
|
||||
* @param onResult callback function
|
||||
*/
|
||||
public uploadTaskDefinition(
|
||||
customHeaders: VsoBaseInterfaces.IHeaders,
|
||||
contentStream: NodeJS.ReadableStream,
|
||||
taskId: string,
|
||||
overwrite: boolean
|
||||
): Promise<void> {
|
||||
|
||||
let promise = this.vsoClient.beginGetLocation("distributedtask", "60aac929-f0cd-4bc8-9ce4-6b30e8f1b1bd")
|
||||
.then((location: ifm.ApiResourceLocation) => {
|
||||
if (location) {
|
||||
// the resource exists at the url we were given. go!
|
||||
return this._uploadTaskDefinition(customHeaders, contentStream, taskId, overwrite);
|
||||
}
|
||||
else {
|
||||
// this is the case when the server doesn't support collection-level task definitions
|
||||
var fallbackClient = this._getFallbackClient(this.baseUrl);
|
||||
if (!fallbackClient) {
|
||||
// couldn't convert
|
||||
throw new Error("Failed to find api location for area: distributedtask id: 60aac929-f0cd-4bc8-9ce4-6b30e8f1b1bd");
|
||||
}
|
||||
else {
|
||||
// use the fallback client
|
||||
return fallbackClient._uploadTaskDefinition(customHeaders, contentStream, taskId, overwrite);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return <Promise<void>>(<any>promise);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {NodeJS.ReadableStream} contentStream
|
||||
* @param {string} taskId
|
||||
* @param {boolean} overwrite
|
||||
* @param onResult callback function
|
||||
*/
|
||||
private _uploadTaskDefinition(
|
||||
public async uploadTaskDefinition(
|
||||
customHeaders: VsoBaseInterfaces.IHeaders,
|
||||
contentStream: NodeJS.ReadableStream,
|
||||
taskId: string,
|
||||
|
@ -217,27 +182,34 @@ export class TaskAgentApi extends taskagentbasem.TaskAgentApiBase implements ITa
|
|||
let queryValues: any = {
|
||||
overwrite: overwrite,
|
||||
};
|
||||
|
||||
customHeaders = customHeaders || {};
|
||||
customHeaders["Content-Type"] = "application/octet-stream";
|
||||
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
this.vsoClient.getVersioningData("3.0-preview.1", "distributedtask", "60aac929-f0cd-4bc8-9ce4-6b30e8f1b1bd", routeValues, queryValues)
|
||||
.then((versioningData: vsom.ClientVersioningData) => {
|
||||
var url: string = versioningData.requestUrl;
|
||||
var apiVersion: string = versioningData.apiVersion;
|
||||
var serializationData = { responseIsCollection: false };
|
||||
return new Promise<void>(async (resolve, reject) => {
|
||||
let routeValues: any = {
|
||||
};
|
||||
|
||||
this.restCallbackClient.uploadStream('PUT', url, apiVersion, contentStream, customHeaders, (err: any, statusCode: number, obj: any) => {
|
||||
if (err) {
|
||||
err.statusCode = statusCode;
|
||||
reject(err);
|
||||
}
|
||||
else {
|
||||
resolve(null);
|
||||
}
|
||||
}, serializationData);
|
||||
});
|
||||
customHeaders = customHeaders || {};
|
||||
customHeaders["Content-Type"] = "application/octet-stream";
|
||||
|
||||
try {
|
||||
let verData: vsom.ClientVersioningData = await this.vsoClient.getVersioningData(
|
||||
"3.0-preview.1",
|
||||
"distributedtask",
|
||||
"60aac929-f0cd-4bc8-9ce4-6b30e8f1b1bd", routeValues, queryValues);
|
||||
|
||||
let url: string = verData.requestUrl;
|
||||
|
||||
let options: restm.IRequestOptions = this.createRequestOptions('application/json',
|
||||
verData.apiVersion);
|
||||
options.additionalHeaders = customHeaders;
|
||||
|
||||
let res: restm.IRestResponse<void>;
|
||||
res = await this.rest.uploadStream<void>("POST", url, contentStream, options);
|
||||
|
||||
resolve(res.result);
|
||||
}
|
||||
catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
import url = require("url");
|
||||
import path = require("path");
|
||||
/// Import base rest class ///
|
||||
import restm = require("./RestClient");
|
||||
import httpm = require("./HttpClient");
|
||||
import * as restm from 'typed-rest-client/RestClient';
|
||||
import * as httpm from 'typed-rest-client/HttpClient';
|
||||
import ifm = require("./interfaces/common/VsoBaseInterfaces");
|
||||
|
||||
interface VssApiResourceLocationLookup {
|
||||
|
@ -39,17 +39,16 @@ export class InvalidApiResourceVersionError implements Error {
|
|||
* Base class that should be used (derived from) to make requests to VSS REST apis
|
||||
*/
|
||||
export class VsoClient {
|
||||
|
||||
private static APIS_RELATIVE_PATH = "_apis";
|
||||
private static PREVIEW_INDICATOR = "-preview.";
|
||||
private _locationsByAreaPromises: { [areaName: string]: Promise<VssApiResourceLocationLookup>; };
|
||||
private _initializationPromise: Promise<any>;
|
||||
|
||||
restClient: restm.RestCallbackClient;
|
||||
restClient: restm.RestClient;
|
||||
baseUrl: string;
|
||||
basePath: string;
|
||||
|
||||
constructor(baseUrl: string, restClient: restm.RestCallbackClient) {
|
||||
constructor(baseUrl: string, restClient: restm.RestClient) {
|
||||
this.baseUrl = baseUrl;
|
||||
this.basePath = url.parse(baseUrl).pathname;
|
||||
this.restClient = restClient;
|
||||
|
@ -170,25 +169,21 @@ export class VsoClient {
|
|||
|
||||
areaLocationsPromise = new Promise<VssApiResourceLocationLookup>((resolve, reject) => {
|
||||
let requestUrl = this.resolveUrl(VsoClient.APIS_RELATIVE_PATH + "/" + area);
|
||||
this.restClient.options<any>(requestUrl)
|
||||
.then((res:restm.IRestResponse<any>) => {
|
||||
let locationsLookup: VssApiResourceLocationLookup = {};
|
||||
let resourceLocations: ifm.ApiResourceLocation[] = res.result.value;
|
||||
|
||||
this._issueOptionsRequest(requestUrl, (err: any, statusCode: number, locationsResult: any) => {
|
||||
if (err) {
|
||||
err.statusCode = statusCode;
|
||||
reject(err);
|
||||
let i;
|
||||
for (i = 0; i < resourceLocations.length; i++) {
|
||||
let resourceLocation = resourceLocations[i];
|
||||
locationsLookup[resourceLocation.id.toLowerCase()] = resourceLocation;
|
||||
}
|
||||
else {
|
||||
let locationsLookup: VssApiResourceLocationLookup = {};
|
||||
|
||||
let resourceLocations: ifm.ApiResourceLocation[] = locationsResult.value;
|
||||
|
||||
let i;
|
||||
for (i = 0; i < locationsResult.count; i++) {
|
||||
let resourceLocation = resourceLocations[i];
|
||||
locationsLookup[resourceLocation.id.toLowerCase()] = resourceLocation;
|
||||
}
|
||||
|
||||
resolve(locationsLookup);
|
||||
}
|
||||
resolve(locationsLookup);
|
||||
})
|
||||
.catch((err) => {
|
||||
reject(err);
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -202,13 +197,6 @@ export class VsoClient {
|
|||
return url.resolve(this.baseUrl, path.join(this.basePath, relativeUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Issues an OPTIONS request to get location objects from a location id
|
||||
*/
|
||||
public _issueOptionsRequest(requestUrl: string, onResult: (err: any, statusCode: number, locationsResult: any) => void): void {
|
||||
return this.restClient.options(requestUrl, onResult);
|
||||
}
|
||||
|
||||
private getSerializedObject(object: any): string {
|
||||
let value:string = "";
|
||||
let first:boolean = true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "vso-node-api",
|
||||
"description": "Node client for Visual Studio Online/TFS REST APIs",
|
||||
"version": "6.1.2-preview",
|
||||
"version": "6.2.0-preview",
|
||||
"main": "./WebApi.js",
|
||||
"typings": "./WebApi.d.ts",
|
||||
"scripts": {
|
||||
|
@ -23,7 +23,7 @@
|
|||
"dependencies": {
|
||||
"q": "^1.0.1",
|
||||
"tunnel": "0.0.4",
|
||||
"typed-rest-client": "^0.9.0",
|
||||
"typed-rest-client": "^0.10.0",
|
||||
"underscore": "^1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
122
samples/http.ts
122
samples/http.ts
|
@ -1,122 +0,0 @@
|
|||
import * as cm from './common';
|
||||
import * as httpm from 'vso-node-api/HttpClient';
|
||||
import * as restm from 'vso-node-api/RestClient';
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
|
||||
let sampleFilePath: string = path.join(process.cwd(), 'httpClientStreamSample.txt');
|
||||
|
||||
let httpc: httpm.HttpClient = new httpm.HttpClient('vsts-node-api');
|
||||
let restc: restm.RestClient = new restm.RestClient('vsts-http');
|
||||
|
||||
export async function run() {
|
||||
let restRes: restm.IRestClientResponse;
|
||||
|
||||
try {
|
||||
//--------------------------------------
|
||||
// HttpClient
|
||||
//--------------------------------------
|
||||
|
||||
//
|
||||
// Http get. Can await get response.
|
||||
// The response offers a message (IncomingMessage) and
|
||||
// an awaitable readBody() which reads the stream to end
|
||||
//
|
||||
cm.heading('get request output body');
|
||||
let res: httpm.HttpClientResponse = await httpc.get('https://httpbin.org/get');
|
||||
let status: number = res.message.statusCode;
|
||||
let body: string = await res.readBody();
|
||||
outputHttpBinResponse(body, status);
|
||||
|
||||
//
|
||||
// Http get request reading body to end in a single line
|
||||
//
|
||||
cm.heading('get request in a single line');
|
||||
body = await (await httpc.get('https://httpbin.org/get')).readBody();
|
||||
outputHttpBinResponse(body);
|
||||
|
||||
//
|
||||
// Http get piping to another stream
|
||||
// response message is an IncomingMessage which is a stream
|
||||
//
|
||||
cm.heading('get request and pipe stream');
|
||||
let file: NodeJS.WritableStream = fs.createWriteStream(sampleFilePath);
|
||||
(await httpc.get('https://httpbin.org/get')).message.pipe(file);
|
||||
body = fs.readFileSync(sampleFilePath).toString();
|
||||
outputHttpBinResponse(body);
|
||||
|
||||
// DELETE request
|
||||
cm.heading('delete request');
|
||||
res = await httpc.del('https://httpbin.org/delete');
|
||||
body = await res.readBody();
|
||||
outputHttpBinResponse(body, status);
|
||||
|
||||
let b: string = 'Hello World!';
|
||||
|
||||
// POST request
|
||||
cm.heading('post request');
|
||||
res = await httpc.post('https://httpbin.org/post', b);
|
||||
body = await res.readBody();
|
||||
outputHttpBinResponse(body, status);
|
||||
|
||||
// PATCH request
|
||||
cm.heading('patch request');
|
||||
res = await httpc.patch('https://httpbin.org/patch', b);
|
||||
body = await res.readBody();
|
||||
outputHttpBinResponse(body, status);
|
||||
|
||||
// GET not found
|
||||
cm.heading('get not found');
|
||||
res = await httpc.get('https://httpbin.org/status/404');
|
||||
body = await res.readBody();
|
||||
outputHttpBinResponse(body, status);
|
||||
|
||||
//--------------------------------------
|
||||
// RestClient
|
||||
//--------------------------------------
|
||||
cm.heading('get rest obj');
|
||||
restRes = await restc.get('https://httpbin.org/get', '1.0-preview');
|
||||
outputRestResponse(restRes);
|
||||
|
||||
let obj: any = { message: "Hello World!" };
|
||||
|
||||
cm.heading('create rest obj');
|
||||
restRes = await restc.create('https://httpbin.org/post', '1.0-preview', obj);
|
||||
outputRestResponse(restRes);
|
||||
|
||||
cm.heading('update rest obj');
|
||||
restRes = await restc.update('https://httpbin.org/patch', '1.0-preview', obj);
|
||||
outputRestResponse(restRes);
|
||||
}
|
||||
catch (err) {
|
||||
console.error('Failed: ' + err.message);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Utility functions
|
||||
//
|
||||
async function outputHttpBinResponse(body: string, status?: number) {
|
||||
if (status) {
|
||||
console.log('status', status);
|
||||
}
|
||||
|
||||
if (body) {
|
||||
let obj = JSON.parse(body.toString());
|
||||
console.log('response from ' + obj.url);
|
||||
if (obj.data) {
|
||||
console.log('data:', obj.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function outputRestResponse(res: restm.IRestClientResponse) {
|
||||
console.log('statusCode:' + res.statusCode);
|
||||
|
||||
if (res && res.result) {
|
||||
console.log('response from ' + res.result.url);
|
||||
if (res.result.data) {
|
||||
console.log('data:', res.result.data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,4 @@
|
|||
[
|
||||
"build",
|
||||
"http",
|
||||
"task"
|
||||
]
|
|
@ -6,7 +6,6 @@
|
|||
},
|
||||
"files": [
|
||||
"run.ts",
|
||||
"http.ts",
|
||||
"build.ts",
|
||||
"task.ts"
|
||||
]
|
||||
|
|
Загрузка…
Ссылка в новой задаче