diff --git a/demo/webpack.config.ts b/demo/webpack.config.ts index d5fbe807..a85fa226 100644 --- a/demo/webpack.config.ts +++ b/demo/webpack.config.ts @@ -45,6 +45,26 @@ const babelLoader = mode => ({ }, }); +let proxy = {}; +let https = false; +//we are using our own proxy here +if (process.env.PROXY && process.env.USERNAME && process.env.PASSWORD) { + proxy = { + "/api": { + auth: `${process.env.USERNAME}:${process.env.PASSWORD}`, + target: process.env.PROXY, + "secure": false, + changeOrigin: true, + ws: true, + xfwd: true + } + } + https = true; + console.log('Using proxy configuration provided with command line, https in use.\n'); +} else { + console.log('Using proxy from PC/PE local server\n'); +} + export default (env: { playground?: boolean; bench?: boolean } = {}, { mode }) => ({ entry: [ root('../src/polyfills.ts'), @@ -66,6 +86,8 @@ export default (env: { playground?: boolean; bench?: boolean } = {}, { mode }) = port: 9090, disableHostCheck: true, stats: 'minimal', + https, + proxy, }, devtool: 'source-map', diff --git a/package.json b/package.json index e9bdad09..592757f4 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "@types/marked": "^0.3.0", "@types/prismjs": "^1.6.4", "@types/prop-types": "^15.5.2", + "@types/qs": "^6.5.1", "@types/react": "^16.0.41", "@types/react-dom": "^16.0.0", "@types/react-hot-loader": "^3.0.3", @@ -143,7 +144,8 @@ "slugify": "^1.2.1", "stickyfill": "^1.1.1", "styled-components": "^3.2.3", - "swagger2openapi": "^2.11.0" + "swagger2openapi": "^2.11.0", + "whatwg-fetch": "^2.0.4" }, "resolutions": { "@types/chai": "4.0.8", diff --git a/src/components/Console/ConsoleViewer.tsx b/src/components/Console/ConsoleViewer.tsx index ed7fe73f..f09b1d0f 100644 --- a/src/components/Console/ConsoleViewer.tsx +++ b/src/components/Console/ConsoleViewer.tsx @@ -1,5 +1,6 @@ import { observer } from 'mobx-react'; import * as React from 'react'; +import qs = require('qs'); import { OperationModel } from '../../services/models'; import { PayloadSamples } from '../PayloadSamples/PayloadSamples'; import { SourceCodeWithCopy } from '../SourceCode/SourceCode'; @@ -17,10 +18,11 @@ export class ConsoleViewer extends React.Component { operation: OperationModel; visited = new Set(); - onClickSend = () => { + onClickSend = async () => { const ace = this.consoleEditor && this.consoleEditor.editor; //const value = ace && ace.editor && const schema = this.getSchema(); + const { operation } = this.props; //console.log('Schema: ' + JSON.stringify(schema, null, 2)); const value = ace && ace.editor.getValue(); @@ -28,17 +30,75 @@ export class ConsoleViewer extends React.Component { const ref = schema && schema['_$ref']; var valid = window && window.ajv.validate({ $ref: `specs.json${ref}` }, value); - console.log(JSON.stringify(window.ajv.errors)); - if (!valid) { console.warn('INVALID REQUEST!'); } + const endpoint = { + method: operation.httpVerb, + path: operation.servers[0].url + operation.path + } console.log('Value: ' + value); + const result = await this.invoke(endpoint, { 'Content-Type': 'application/*' }, JSON.parse(value)); + console.log('Result: ' + JSON.stringify(result)); + }; + async invoke(endpoint, headers, body) { + + const fetchArgs = { + method: endpoint.method, + headers, + redirect: 'manual', + credentials: 'include' + } + + let url = endpoint.path; + if (endpoint.method.toLocaleLowerCase() === 'get') { + url = url + '?' + qs.stringify(body); + } else { + fetchArgs['body'] = (body) ? JSON.stringify(body) : null; + } + + const result = await fetch(url, fetchArgs); + + const contentType = result.headers.get("content-type"); + if (contentType && contentType.indexOf("application/json") !== -1) { + // successful cross-domain connect/ability + const resp = await result.json(); + + return { json: resp, statusCode: result.status, _fetchRes: result }; + } + else if (result.status === 200 && contentType && contentType.indexOf("text/plain") !== -1) { + const resp = await result.text(); + return { resp, _fetchRes: result }; + } + else { + if (result && result.type && result.type === 'opaqueredirect') { + return { + json: { + endpoint, + error_code: "RECEIVED_LOGIN_REDIRECT", + details: "Your session expired. Please refresh the page.", + severity: "error" + } + } + } + + return { + json: { + endpoint, + error_code: "INVALID_SERVER_RESPONSE", + details: "Either server not authenticated or error on server", + severity: "error" + } + }; + } + } + + render() { const { operation } = this.props; const requestBodyContent = operation.requestBody && operation.requestBody.content && operation.requestBody.content; diff --git a/src/utils/fetch.ts b/src/utils/fetch.ts new file mode 100644 index 00000000..e69de29b diff --git a/yarn.lock b/yarn.lock index 3d99af36..7ff44556 100644 --- a/yarn.lock +++ b/yarn.lock @@ -264,6 +264,10 @@ version "15.5.2" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.5.2.tgz#3c6b8dceb2906cc87fe4358e809f9d20c8d59be1" +"@types/qs@^6.5.1": + version "6.5.1" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.1.tgz#a38f69c62528d56ba7bd1f91335a8004988d72f7" + "@types/react-dom@^16.0.0": version "16.0.4" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.0.4.tgz#2e8fd45f5443780ed49bf2cdd9809e6091177a7d" @@ -9839,6 +9843,10 @@ whatwg-fetch@>=0.10.0: version "2.0.3" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84" +whatwg-fetch@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" + whatwg-url@^6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-6.4.0.tgz#08fdf2b9e872783a7a1f6216260a1d66cc722e08"