mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-19 21:57:13 -04:00
A bunch of fixes with OAuth and minor network bugs (#155)
* A bunch of fixes with OAuth and minor network bugs * Handle charsets and only autocomplete constants if exact prefix * Fix head requests * Fix double submisson of request * Fixed tests
This commit is contained in:
4
.editorconfig
Normal file
4
.editorconfig
Normal file
@@ -0,0 +1,4 @@
|
||||
[*.{js,json,html}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@@ -88,6 +88,7 @@ Curl.option = {
|
||||
DEBUGFUNCTION: 'DEBUGFUNCTION',
|
||||
ACCEPT_ENCODING: 'ACCEPT_ENCODING',
|
||||
FOLLOWLOCATION: 'FOLLOWLOCATION',
|
||||
NOBODY: 'NOBODY',
|
||||
HTTPAUTH: 'HTTPAUTH',
|
||||
HTTPHEADER: 'HTTPHEADER',
|
||||
HTTPPOST: 'HTTPPOST',
|
||||
|
||||
@@ -121,6 +121,7 @@ describe('updateMimeType()', async () => {
|
||||
expect(request).not.toBeNull();
|
||||
|
||||
const newRequest = await requestModel.updateMimeType(request, null);
|
||||
expect(newRequest.body).toEqual({});
|
||||
expect(newRequest.headers).toEqual([]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -144,12 +144,12 @@ export function updateMimeType (request, mimeType, doCreate = false) {
|
||||
// 1. Update Content-Type header //
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //
|
||||
|
||||
if (!mimeType) {
|
||||
// Remove the contentType header if we are un-setting it
|
||||
const hasBody = typeof mimeType === 'string';
|
||||
if (!hasBody) {
|
||||
headers = headers.filter(h => h !== contentTypeHeader);
|
||||
} else if (contentTypeHeader) {
|
||||
} else if (mimeType && contentTypeHeader) {
|
||||
contentTypeHeader.value = mimeType;
|
||||
} else {
|
||||
} else if (mimeType && !contentTypeHeader) {
|
||||
headers.push({name: 'Content-Type', value: mimeType});
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@ describe('actuallySend()', () => {
|
||||
],
|
||||
CUSTOMREQUEST: 'POST',
|
||||
ACCEPT_ENCODING: '',
|
||||
NOBODY: 0,
|
||||
FOLLOWLOCATION: true,
|
||||
HTTPHEADER: [
|
||||
'Content-Type: application/json',
|
||||
@@ -161,6 +162,7 @@ describe('actuallySend()', () => {
|
||||
USERNAME: 'user',
|
||||
PASSWORD: 'pass',
|
||||
POSTFIELDS: 'foo=bar',
|
||||
NOBODY: 0,
|
||||
PROXY: '',
|
||||
TIMEOUT_MS: 0,
|
||||
URL: 'http://localhost/?foo%20bar=hello%26world',
|
||||
@@ -214,6 +216,7 @@ describe('actuallySend()', () => {
|
||||
],
|
||||
NOPROGRESS: false,
|
||||
PROXY: '',
|
||||
NOBODY: 0,
|
||||
TIMEOUT_MS: 0,
|
||||
UPLOAD: 1,
|
||||
URL: 'http://localhost/',
|
||||
@@ -273,6 +276,7 @@ describe('actuallySend()', () => {
|
||||
],
|
||||
NOPROGRESS: false,
|
||||
PROXY: '',
|
||||
NOBODY: 0,
|
||||
TIMEOUT_MS: 0,
|
||||
URL: 'http://localhost/',
|
||||
USERAGENT: `insomnia/${getAppVersion()}`,
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as models from '../models';
|
||||
import * as querystring from '../common/querystring';
|
||||
import * as util from '../common/misc.js';
|
||||
import {AUTH_BASIC, AUTH_DIGEST, AUTH_NTLM, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED, DEBOUNCE_MILLIS, getAppVersion} from '../common/constants';
|
||||
import {describeByteSize, hasAcceptHeader, hasAuthHeader, hasContentTypeHeader, hasUserAgentHeader, setDefaultProtocol} from '../common/misc';
|
||||
import {describeByteSize, hasAuthHeader, hasContentTypeHeader, hasUserAgentHeader, setDefaultProtocol} from '../common/misc';
|
||||
import {getRenderedRequest} from '../common/render';
|
||||
import fs from 'fs';
|
||||
import * as db from '../common/database';
|
||||
@@ -84,10 +84,12 @@ export function _actuallySend (renderedRequest, workspace, settings) {
|
||||
|
||||
// Set all the basic options
|
||||
setOpt(Curl.option.CUSTOMREQUEST, renderedRequest.method);
|
||||
setOpt(Curl.option.NOBODY, renderedRequest.method.toLowerCase() === 'head' ? 1 : 0);
|
||||
setOpt(Curl.option.FOLLOWLOCATION, settings.followRedirects);
|
||||
setOpt(Curl.option.TIMEOUT_MS, settings.timeout); // 0 for no timeout
|
||||
setOpt(Curl.option.VERBOSE, true); // True so debug function works
|
||||
setOpt(Curl.option.NOPROGRESS, false); // False so progress function works
|
||||
setOpt(Curl.option.ACCEPT_ENCODING, ''); // Auto decode everything
|
||||
|
||||
// Setup debug handler
|
||||
setOpt(Curl.option.DEBUGFUNCTION, (infoType, content) => {
|
||||
@@ -371,11 +373,6 @@ export function _actuallySend (renderedRequest, workspace, settings) {
|
||||
setOpt(Curl.option.USERAGENT, `insomnia/${getAppVersion()}`);
|
||||
}
|
||||
|
||||
// Set Accept encoding
|
||||
if (!hasAcceptHeader(headers)) {
|
||||
setOpt(Curl.option.ACCEPT_ENCODING, ''); // Accept anything
|
||||
}
|
||||
|
||||
// Prevent curl from adding default content-type header
|
||||
if (!hasContentTypeHeader(headers)) {
|
||||
headers.push({name: 'content-type', value: ''});
|
||||
|
||||
@@ -2,6 +2,7 @@ export const GRANT_TYPE_AUTHORIZATION_CODE = 'authorization_code';
|
||||
export const GRANT_TYPE_IMPLICIT = 'implicit';
|
||||
export const GRANT_TYPE_PASSWORD = 'password';
|
||||
export const GRANT_TYPE_CLIENT_CREDENTIALS = 'client_credentials';
|
||||
export const GRANT_TYPE_REFRESH = 'refresh_token';
|
||||
|
||||
export const RESPONSE_TYPE_CODE = 'code';
|
||||
export const RESPONSE_TYPE_TOKEN = 'token';
|
||||
|
||||
@@ -139,7 +139,7 @@ async function _getAccessToken (requestId, authentication, forceRefresh) {
|
||||
authentication.credentialsInBody,
|
||||
authentication.clientId,
|
||||
authentication.clientSecret,
|
||||
authentication.refreshToken,
|
||||
token.refreshToken,
|
||||
authentication.scope
|
||||
);
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ export function responseToObject (body, keys) {
|
||||
|
||||
let results = {};
|
||||
for (const key of keys) {
|
||||
const value = typeof data[key] === 'string' ? data[key] : null;
|
||||
const value = data[key] !== undefined ? data[key] : null;
|
||||
results[key] = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ export default async function (accessTokenUrl,
|
||||
refreshToken,
|
||||
scope = '') {
|
||||
const params = [
|
||||
{name: c.P_GRANT_TYPE, value: c.GRANT_TYPE_IMPLICIT},
|
||||
{name: c.P_GRANT_TYPE, value: c.GRANT_TYPE_REFRESH},
|
||||
{name: c.P_REFRESH_TOKEN, value: refreshToken}
|
||||
];
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import NeDB from 'nedb';
|
||||
import fsPath from 'path';
|
||||
import crypto from 'crypto';
|
||||
import * as util from '../common/misc';
|
||||
import {DB_PERSIST_INTERVAL} from '../common/constants';
|
||||
|
||||
const TYPE_RESOURCE = 'Resource';
|
||||
const TYPE_CONFIG = 'Config';
|
||||
@@ -181,6 +182,10 @@ export function initDB (config, forceReset) {
|
||||
Object.assign({filename: configPath, autoload: true}, config)
|
||||
);
|
||||
|
||||
for (const key of Object.keys(_database)) {
|
||||
_database[key].persistence.setAutocompactionInterval(DB_PERSIST_INTERVAL);
|
||||
}
|
||||
|
||||
// Done
|
||||
console.log(`-- Initialize Sync DB at ${basePath} --`);
|
||||
}
|
||||
|
||||
@@ -178,6 +178,7 @@ function hint (cm, options) {
|
||||
const nameMatchLong = previousText.match(NAME_MATCH_FLEXIBLE);
|
||||
const nameSegment = nameMatch ? nameMatch[0] : fallbackSegment;
|
||||
const nameSegmentLong = nameMatchLong ? nameMatchLong[0] : fallbackSegment;
|
||||
const nameSegmentFull = previousText;
|
||||
|
||||
// Actually try to match the list of things
|
||||
const allShortMatches = [];
|
||||
@@ -195,9 +196,8 @@ function hint (cm, options) {
|
||||
// TODO: Make this more flexible. This is really only here as a hack to make
|
||||
// constants only match full string prefixes.
|
||||
if (allowMatchingConstants) {
|
||||
// matchSegments(constantsToMatch, nameSegment, TYPE_CONSTANT, MAX_CONSTANTS)
|
||||
// .map(m => allShortMatches.push(m));
|
||||
matchSegments(constantsToMatch, nameSegmentLong, TYPE_CONSTANT, MAX_CONSTANTS)
|
||||
// Only match full segments with constants
|
||||
matchSegments(constantsToMatch, nameSegmentFull, TYPE_CONSTANT, MAX_CONSTANTS)
|
||||
.map(m => allLongMatches.push(m));
|
||||
}
|
||||
|
||||
|
||||
@@ -190,6 +190,8 @@ class OneLineEditor extends PureComponent {
|
||||
for (let i = 0; i < 20 && node; i++) {
|
||||
if (node.tagName === 'FORM') {
|
||||
node.dispatchEvent(new window.Event('submit'));
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
break;
|
||||
}
|
||||
node = node.parentNode;
|
||||
@@ -254,7 +256,7 @@ class OneLineEditor extends PureComponent {
|
||||
}
|
||||
|
||||
_mayContainNunjucks (text) {
|
||||
return !!text.match(NUNJUCKS_REGEX);
|
||||
return !!(text && text.match(NUNJUCKS_REGEX));
|
||||
}
|
||||
|
||||
render () {
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, {PropTypes, PureComponent} from 'react';
|
||||
import moment from 'moment';
|
||||
import autobind from 'autobind-decorator';
|
||||
import OneLineEditor from '../../codemirror/one-line-editor';
|
||||
import * as misc from '../../../../common/misc';
|
||||
@@ -288,11 +289,13 @@ class OAuth2 extends PureComponent {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!token.expireAt) {
|
||||
if (!token.expiresAt) {
|
||||
return '(never expires)';
|
||||
}
|
||||
|
||||
return `(expires ${new Date(token.expireAt)})`;
|
||||
const expiresAt = new Date(token.expiresAt);
|
||||
const str = moment(expiresAt).fromNow();
|
||||
return <span title={expiresAt.toString()}>(expires {str})</span>;
|
||||
}
|
||||
|
||||
render () {
|
||||
@@ -345,7 +348,6 @@ class OAuth2 extends PureComponent {
|
||||
<label>
|
||||
<small>
|
||||
Refresh Token
|
||||
{(tok && tok.refreshToken) ? <em> {expireLabel}</em> : null}
|
||||
</small>
|
||||
<input value={(tok && tok.refreshToken) || ''}
|
||||
placeholder="n/a"
|
||||
@@ -355,8 +357,7 @@ class OAuth2 extends PureComponent {
|
||||
<div className="form-control form-control--outlined">
|
||||
<label>
|
||||
<small>
|
||||
Access Token
|
||||
{(tok && !tok.refreshToken) ? <em> {expireLabel}</em> : null}
|
||||
Access Token {tok ? <em>{expireLabel}</em> : null}
|
||||
</small>
|
||||
<input value={(tok && tok.accessToken) || ''}
|
||||
placeholder="n/a"
|
||||
|
||||
@@ -31,10 +31,10 @@ class RequestHeadersEditor extends PureComponent {
|
||||
const rows = headersString.split(/[\n,]+/);
|
||||
|
||||
for (const row of rows) {
|
||||
const items = row.split(':');
|
||||
const [rawName, ...items] = row.split(':');
|
||||
|
||||
const name = (items[0] || '').trim();
|
||||
const value = (items[1] || '').trim();
|
||||
const name = (rawName || '').trim();
|
||||
const value = (items.join(':')).trim();
|
||||
|
||||
headers.push({name, value});
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, {PropTypes, PureComponent} from 'react';
|
||||
import iconv from 'iconv-lite';
|
||||
import autobind from 'autobind-decorator';
|
||||
import {shell} from 'electron';
|
||||
import CodeEditor from '../codemirror/code-editor';
|
||||
@@ -141,24 +142,31 @@ class ResponseViewer extends PureComponent {
|
||||
</div>
|
||||
);
|
||||
} else if (previewMode === PREVIEW_MODE_FRIENDLY && ct.includes('html')) {
|
||||
const justContentType = contentType.split(';')[0];
|
||||
const match = contentType.match(/charset=([\w-]+)/);
|
||||
const charset = (match && match.length >= 2) ? match[1] : 'utf-8';
|
||||
return (
|
||||
<ResponseWebView
|
||||
body={bodyBuffer.toString('utf8')}
|
||||
contentType={contentType}
|
||||
body={iconv.decode(bodyBuffer, charset)}
|
||||
contentType={`${justContentType}; charset=UTF-8`}
|
||||
url={url}
|
||||
/>
|
||||
);
|
||||
} else if (previewMode === PREVIEW_MODE_RAW) {
|
||||
const match = contentType.match(/charset=([\w-]+)/);
|
||||
const charset = (match && match.length >= 2) ? match[1] : 'utf-8';
|
||||
return (
|
||||
<ResponseRaw
|
||||
value={bodyBuffer.toString('utf8')}
|
||||
value={iconv.decode(bodyBuffer, charset)}
|
||||
fontSize={editorFontSize}
|
||||
/>
|
||||
);
|
||||
} else { // Show everything else as "source"
|
||||
let mode = contentType;
|
||||
const body = bodyBuffer.toString('utf8');
|
||||
const match = contentType.match(/charset=([\w-]+)/);
|
||||
const charset = (match && match.length >= 2) ? match[1] : 'utf-8';
|
||||
const body = iconv.decode(bodyBuffer, charset);
|
||||
|
||||
let mode = contentType;
|
||||
try {
|
||||
// FEATURE: Detect JSON even without content-type
|
||||
contentType.indexOf('json') === -1 && JSON.parse(body);
|
||||
|
||||
@@ -109,11 +109,13 @@
|
||||
"hkdf": "0.0.2",
|
||||
"html-entities": "^1.2.0",
|
||||
"httpsnippet": "1.16.5",
|
||||
"iconv-lite": "^0.4.15",
|
||||
"insomnia-importers": "~1.3.1",
|
||||
"jsonlint": "~1.6.2",
|
||||
"jsonpath": "~0.2.11",
|
||||
"mime-types": "~2.1.14",
|
||||
"mkdirp": "~0.5.1",
|
||||
"moment": "^2.18.1",
|
||||
"nedb": "~1.8.0",
|
||||
"node-forge": "~0.7.0",
|
||||
"node-libcurl": "git://github.com/getinsomnia/node-libcurl.git#3fc2afea435f3548eedbef9c68d3fee642dfcddb",
|
||||
|
||||
Reference in New Issue
Block a user