UNPKG

@akala/core

Version:
230 lines (205 loc) 8.04 kB
import { register, injectWithName } from "./global-injector"; import { ParsedAny, Parser } from "./parser"; import { each, map, grep } from "./each"; import { extend, module } from "./helpers"; import { service } from "./service"; import { FormatterFactory } from "./formatters/common"; import * as uri from 'url'; import * as qs from 'querystring' import 'isomorphic-fetch'; import { Injected } from "./injector"; export interface HttpOptions { method?: string; url: string | uri.UrlObject; queryString?: any; body?: any; headers?: { [key: string]: string | number | Date }; contentType?: 'json' | 'form'; type?: 'json' | 'xml' | 'text' | 'raw'; } export interface Http<TResponse = Response> { get(url: string, params?: any): PromiseLike<TResponse>; post(url: string, body?: any): PromiseLike<FormData>; postJSON<T = string>(url: string, body?: any): PromiseLike<T>; getJSON<T>(url: string, params?: any): PromiseLike<T>; invokeSOAP(namespace: string, action: string, url: string, params?: { [key: string]: string | number | boolean }): PromiseLike<TResponse>; call(options: HttpOptions): PromiseLike<TResponse>; } @service('$http') export class FetchHttp implements Http<Response> { constructor() { } public get(url: string, params?: any) { return this.call({ url: url, method: 'GET', queryString: params }); } public post(url: string, body?: any): PromiseLike<FormData> { return this.call({ method: 'POST', url: url, body: body }).then((r) => { return r.formData(); }); } public postJSON<T = string>(url: string, body?: any): PromiseLike<T> { return this.call({ method: 'POST', url: url, body: body, contentType: 'json', type: 'json' }).then((r) => { return r.json(); }); } public getJSON<T>(url: string, params?: any): PromiseLike<T> { return this.call({ method: 'GET', url: url, queryString: params, type: 'json' }).then((r) => { return r.json(); }); } public invokeSOAP(namespace: string, action: string, url: string, params?: { [key: string]: string | number | boolean }) { var body = '<?xml version="1.0" encoding="utf-8"?><s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body>' + '<u:' + action + ' xmlns:u="' + namespace + '">'; each(params, function (paramValue, paramName) { body += '<' + paramName + '><![CDATA[' + paramValue + ']]></' + paramName + '>'; }); body += '</u:' + action + '></s:Body></s:Envelope>'; return this.call({ method: 'POST', url: url, type: 'xml', headers: { SOAPAction: namespace + '#' + action }, body: body }); } public call(options: HttpOptions): Promise<Response> { var init: RequestInit = { method: options.method || 'GET', body: options.body }; if (typeof (options.url) == 'string') options.url = uri.parse(options.url, true); if (options.queryString) { if (typeof (options.queryString) == 'string') options.queryString = qs.parse(options.queryString); options.url.query = extend(options.url.query, options.queryString); } if (options.headers) { init.headers = {}; each(options.headers, function (value, key) { if (value instanceof Date) init.headers[key as string] = value.toJSON(); else init.headers[key as string] = value && value.toString(); }); } if (options.type) { init.headers = init.headers || {}; switch (options.type) { case 'json': init.headers['Accept'] = 'application/json, text/json'; if (!options.contentType && typeof (init.body) !== 'string') init.body = JSON.stringify(init.body); break; case 'xml': init.headers['Accept'] = 'text/xml'; break; case 'text': init.headers['Accept'] = 'text/plain'; break; } } if (options.contentType && options.body) { init.headers = init.headers || {}; switch (options.contentType) { case 'json': init.headers['Content-Type'] = 'application/json; charset=UTF-8' if (typeof (init.body) !== 'string') init.body = JSON.stringify(init.body); break; case 'form': init.headers['Content-Type'] = 'multipart/form-data'; if (!(init.body instanceof FormData) && typeof init.body == 'undefined') init.body = FetchHttp.serialize(init.body); break; } } return fetch(uri.format(options.url), init); } public static serialize(obj, prefix?: string) { return map(obj, function (value, key: string) { if (typeof (value) == 'object') { var keyPrefix = prefix; if (prefix) { if (typeof (key) == 'number') keyPrefix = prefix.substring(0, prefix.length - 1) + '[' + key + '].'; else keyPrefix = prefix + encodeURIComponent(key) + '.'; } return FetchHttp.serialize(value, keyPrefix); } else { return (prefix || '') + encodeURIComponent(key) + '=' + encodeURIComponent(value); } }, true) } } export class HttpCallFormatterFactory implements FormatterFactory<() => Promise<any>, { method?: keyof Http }> { constructor() { } public parse(expression: string): { method?: keyof Http } & ParsedAny { var method = /^ *(\w+)/.exec(expression); if (method) return { method: <keyof Http>method[1], $$length: method[0].length }; return Parser.parseAny(expression, false); } public build(formatter, settings: { method: keyof Http }): Injected<any> { if (!settings) settings = { method: 'getJSON' }; return function (scope) { var settingsValue = settings as HttpOptions & { method?: keyof Http }; if (settings instanceof Function) settingsValue = settings(scope); return injectWithName(['$http'], function (http: Http) { var formattedValue = formatter(scope); if (typeof (formattedValue) == 'string') return (http[settingsValue.method || 'getJSON'] as Function)(formattedValue, grep(settingsValue, function (value, key) { return key != 'method'; })); if (Array.isArray(formattedValue)) { return (http[settingsValue.method || 'getJSON'] as Function).apply(http, formattedValue); } return (http[settingsValue.method || 'getJSON'] as Function)(formattedValue); }); } } } export class HttpFormatterFactory extends HttpCallFormatterFactory implements FormatterFactory<Promise<any>, { method?: keyof Http }> { constructor() { super(); } public build(formatter, settings: { method: keyof Http }) { return (value) => { return super.build(formatter, settings)(value)(); }; } } module('$formatters').register('#http', new HttpFormatterFactory()); module('$formatters').register('#httpCall', new HttpCallFormatterFactory());