mirror of
https://github.com/Redocly/redoc.git
synced 2025-08-09 14:44:51 +03:00
feat: ConsoleViewer can send the proper request customized by user now
This commit is contained in:
parent
e80fe1d47c
commit
2a927eb27c
|
@ -1,8 +1,8 @@
|
|||
openapi: 3.0.0
|
||||
servers:
|
||||
- url: //petstore.swagger.io/v2
|
||||
- url: https://petstore.swagger.io/v2
|
||||
description: Default server
|
||||
- url: //petstore.swagger.io/sandbox
|
||||
- url: https://petstore.swagger.io/sandbox
|
||||
description: Sandbox server
|
||||
info:
|
||||
description: |
|
||||
|
@ -101,7 +101,7 @@ paths:
|
|||
'405':
|
||||
description: Invalid input
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
x-code-samples:
|
||||
|
@ -149,7 +149,7 @@ paths:
|
|||
'405':
|
||||
description: Validation exception
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
x-code-samples:
|
||||
|
@ -217,7 +217,7 @@ paths:
|
|||
'405':
|
||||
description: Invalid input
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
requestBody:
|
||||
|
@ -256,7 +256,7 @@ paths:
|
|||
'400':
|
||||
description: Invalid pet value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
'/pet/{petId}/uploadImage':
|
||||
|
@ -282,7 +282,7 @@ paths:
|
|||
schema:
|
||||
$ref: '#/components/schemas/ApiResponse'
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
requestBody:
|
||||
|
@ -332,7 +332,7 @@ paths:
|
|||
'400':
|
||||
description: Invalid status value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
/pet/findByTags:
|
||||
|
@ -372,7 +372,7 @@ paths:
|
|||
'400':
|
||||
description: Invalid tag value
|
||||
security:
|
||||
- petstore_auth:
|
||||
- authorization:
|
||||
- 'write:pets'
|
||||
- 'read:pets'
|
||||
/store/inventory:
|
||||
|
@ -923,7 +923,7 @@ components:
|
|||
description: List of user object
|
||||
required: true
|
||||
securitySchemes:
|
||||
petstore_auth:
|
||||
authorization:
|
||||
description: |
|
||||
Get access to data while protecting your account credentials.
|
||||
OAuth2 is also a safer and more secure way to give you access.
|
||||
|
|
|
@ -25,9 +25,7 @@ const specUrl =
|
|||
(userUrl && userUrl[1]) || (swagger ? 'swagger.yaml' : big ? 'big-openapi.json' : 'openapi.yaml');
|
||||
|
||||
let store;
|
||||
const headers = {
|
||||
'x-nutanix-client': 'ui',
|
||||
};
|
||||
const headers = {};
|
||||
const options: RedocRawOptions = { nativeScrollbars: false, enableConsole: true, providedByName: 'Intent ApiDocs by Nutanix', providedByUri: 'http://www.nutanix.com', additionalHeaders: headers };
|
||||
|
||||
async function init() {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { SecuritySchemeModel } from '../../../typings/services/models';
|
||||
import { SubmitButton } from '../../common-elements/buttons';
|
||||
import { FlexLayoutReverse } from '../../common-elements/panels';
|
||||
import { FieldModel, OperationModel } from '../../services/models';
|
||||
import { OpenAPISchema } from '../../types';
|
||||
import { FieldModel, OperationModel, SecuritySchemesModel } from '../../services/models';
|
||||
import { SourceCodeWithCopy } from '../SourceCode/SourceCode';
|
||||
import { ConsoleEditor } from './ConsoleEditor';
|
||||
|
||||
|
@ -14,6 +14,7 @@ export interface ConsoleViewerProps {
|
|||
additionalHeaders?: object;
|
||||
queryParamPrefix?: string;
|
||||
queryParamSuffix?: string;
|
||||
securitySchemes: SecuritySchemesModel;
|
||||
}
|
||||
|
||||
export interface ConsoleViewerState {
|
||||
|
@ -22,7 +23,6 @@ export interface ConsoleViewerState {
|
|||
|
||||
export interface Schema {
|
||||
_$ref?: any;
|
||||
rawSchema?: OpenAPISchema;
|
||||
}
|
||||
|
||||
@observer
|
||||
|
@ -40,7 +40,8 @@ export class ConsoleViewer extends React.Component<ConsoleViewerProps, ConsoleVi
|
|||
}
|
||||
onClickSend = async () => {
|
||||
const ace = this.consoleEditor && this.consoleEditor.editor;
|
||||
const { operation, additionalHeaders = {} } = this.props;
|
||||
const { operation, securitySchemes: {schemes}, additionalHeaders = {} } = this.props;
|
||||
|
||||
let value = ace && ace.editor.getValue();
|
||||
|
||||
const content = operation.requestBody && operation.requestBody.content;
|
||||
|
@ -54,7 +55,23 @@ export class ConsoleViewer extends React.Component<ConsoleViewerProps, ConsoleVi
|
|||
}
|
||||
const contentType = mediaType && mediaType.name || 'application/json';
|
||||
const contentTypeHeader = { 'Content-Type': contentType };
|
||||
const headers = { ...additionalHeaders, ...contentTypeHeader };
|
||||
|
||||
const schemeMapper: Map<string, SecuritySchemeModel> = new Map<string, SecuritySchemeModel>();
|
||||
schemes.forEach(scheme => {
|
||||
schemeMapper.set(scheme.id, scheme);
|
||||
});
|
||||
|
||||
const securityHeaders: Dict<string | undefined> = {};
|
||||
|
||||
operation.security.forEach(({schemes: [{ id }]}) => {
|
||||
if (schemeMapper.has(id)) {
|
||||
// this part of code needs a ts-ignore because typescript couldn't detect that schemeMapper.get(id) -
|
||||
// has been checked to avoid token of undefined.
|
||||
// @ts-ignore
|
||||
securityHeaders[id] = schemeMapper.get(id).token;
|
||||
}
|
||||
});
|
||||
const headers = { ...additionalHeaders, ...contentTypeHeader, ...securityHeaders };
|
||||
let result;
|
||||
try {
|
||||
result = await this.invoke(endpoint, value, headers);
|
||||
|
@ -76,8 +93,6 @@ export class ConsoleViewer extends React.Component<ConsoleViewerProps, ConsoleVi
|
|||
const queryParamSuffix = '}';
|
||||
|
||||
for (const fieldModel of params) {
|
||||
console.log(fieldModel.name + ' ' + url);
|
||||
console.log(fieldModel.$value);
|
||||
if (url.indexOf(`${queryParamPrefix}${fieldModel.name}${queryParamSuffix}`) > -1 && fieldModel.$value.length > 0) {
|
||||
url = url.replace(`${queryParamPrefix}${fieldModel.name}${queryParamSuffix}`, fieldModel.$value);
|
||||
}
|
||||
|
@ -106,7 +121,6 @@ export class ConsoleViewer extends React.Component<ConsoleViewerProps, ConsoleVi
|
|||
|
||||
const request = new Request(url, {
|
||||
method: endpoint.method,
|
||||
credentials: 'include',
|
||||
redirect: 'manual',
|
||||
headers: myHeaders,
|
||||
body: (body) ? JSON.stringify(body) : undefined,
|
||||
|
@ -173,29 +187,4 @@ export class ConsoleViewer extends React.Component<ConsoleViewerProps, ConsoleVi
|
|||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
getSchema() {
|
||||
const { operation } = this.props;
|
||||
const requestBodyContent = operation.requestBody && operation.requestBody.content && operation.requestBody.content;
|
||||
const mediaTypes = (requestBodyContent && requestBodyContent.mediaTypes) ? requestBodyContent.mediaTypes : [];
|
||||
|
||||
if (!mediaTypes.length) {
|
||||
return null;
|
||||
}
|
||||
const schema: Schema = {
|
||||
};
|
||||
for (const mediaType of mediaTypes) {
|
||||
if (mediaType.name.indexOf('json') > -1) {
|
||||
if (mediaType.schema) {
|
||||
schema.rawSchema = mediaType.schema && mediaType.schema.rawSchema;
|
||||
console.log('rawSchema : ' + JSON.stringify(schema));
|
||||
console.log('schema : ' + JSON.stringify(mediaType.schema.schema));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return schema;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,35 +1,40 @@
|
|||
import { observer } from 'mobx-react';
|
||||
import * as React from 'react';
|
||||
import { AppStore } from '../../services';
|
||||
|
||||
import { ExternalDocumentation } from '../ExternalDocumentation/ExternalDocumentation';
|
||||
import { AdvancedMarkdown } from '../Markdown/AdvancedMarkdown';
|
||||
|
||||
import { H1, H2, MiddlePanel, Row, Section, ShareLink } from '../../common-elements';
|
||||
import { ContentItemModel } from '../../services/MenuBuilder';
|
||||
import { GroupModel, OperationModel } from '../../services/models';
|
||||
import { GroupModel } from '../../services/models';
|
||||
import { Operation } from '../Operation/Operation';
|
||||
|
||||
@observer
|
||||
export class ContentItems extends React.Component<{
|
||||
export interface ContentItemsProps {
|
||||
items: ContentItemModel[];
|
||||
}> {
|
||||
store: AppStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ContentItems extends React.Component<ContentItemsProps> {
|
||||
render() {
|
||||
const items = this.props.items;
|
||||
const { items, store } = this.props;
|
||||
if (items.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return items.map(item => <ContentItem item={item} key={item.id} />);
|
||||
return items.map(item => <ContentItem store={store} item={item} key={item.id} />);
|
||||
}
|
||||
}
|
||||
|
||||
export interface ContentItemProps {
|
||||
item: ContentItemModel;
|
||||
store: AppStore;
|
||||
}
|
||||
|
||||
@observer
|
||||
export class ContentItem extends React.Component<ContentItemProps> {
|
||||
render() {
|
||||
const item = this.props.item;
|
||||
const { item, store } = this.props;
|
||||
let content;
|
||||
const { type } = item;
|
||||
switch (type) {
|
||||
|
@ -41,7 +46,7 @@ export class ContentItem extends React.Component<ContentItemProps> {
|
|||
content = <SectionItem {...this.props} />;
|
||||
break;
|
||||
case 'operation':
|
||||
content = <OperationItem item={item as any} />;
|
||||
content = <Operation securitySchemes={store.spec.securitySchemes} operation={item as any} />;
|
||||
break;
|
||||
default:
|
||||
content = <SectionItem {...this.props} />;
|
||||
|
@ -54,7 +59,7 @@ export class ContentItem extends React.Component<ContentItemProps> {
|
|||
{content}
|
||||
</Section>
|
||||
)}
|
||||
{item.items && <ContentItems items={item.items} />}
|
||||
{item.items && <ContentItems store={store} items={item.items} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -90,12 +95,3 @@ export class SectionItem extends React.Component<ContentItemProps> {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
@observer
|
||||
export class OperationItem extends React.Component<{
|
||||
item: OperationModel;
|
||||
}> {
|
||||
render() {
|
||||
return <Operation operation={this.props.item} />;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { Badge, DarkRightPanel, H2, MiddlePanel, Row } from '../../common-elemen
|
|||
|
||||
import { ShareLink } from '../../common-elements/linkify';
|
||||
|
||||
import { OperationModel as OperationType } from '../../services/models';
|
||||
import { OperationModel as OperationType, SecuritySchemesModel } from '../../services/models';
|
||||
import styled from '../../styled-components';
|
||||
import { ConsoleViewer } from '../Console/ConsoleViewer';
|
||||
import { Endpoint } from '../Endpoint/Endpoint';
|
||||
|
@ -34,6 +34,7 @@ const Description = styled.div`
|
|||
|
||||
export interface OperationProps {
|
||||
operation: OperationType;
|
||||
securitySchemes: SecuritySchemesModel;
|
||||
}
|
||||
|
||||
export interface OperationState {
|
||||
|
@ -57,7 +58,7 @@ export class Operation extends React.Component<OperationProps, OperationState> {
|
|||
}
|
||||
|
||||
render() {
|
||||
const { operation } = this.props;
|
||||
const { operation, securitySchemes } = this.props;
|
||||
const { executeMode } = this.state;
|
||||
|
||||
const { name: summary, description, deprecated, externalDocs } = operation;
|
||||
|
@ -95,7 +96,13 @@ export class Operation extends React.Component<OperationProps, OperationState> {
|
|||
{!options.pathInMiddlePanel && <Endpoint operation={operation} />}
|
||||
{executeMode &&
|
||||
<div>
|
||||
<ConsoleViewer operation={operation} additionalHeaders={options.additionalHeaders} queryParamPrefix={options.queryParamPrefix} queryParamSuffix={options.queryParamSuffix} />
|
||||
<ConsoleViewer
|
||||
securitySchemes={securitySchemes}
|
||||
operation={operation}
|
||||
additionalHeaders={options.additionalHeaders}
|
||||
queryParamPrefix={options.queryParamPrefix}
|
||||
queryParamSuffix={options.queryParamSuffix}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
{!executeMode &&
|
||||
|
|
|
@ -57,7 +57,7 @@ export class Redoc extends React.Component<RedocProps> {
|
|||
</StickyResponsiveSidebar>
|
||||
<ApiContentWrap className="api-content">
|
||||
<ApiInfo store={store} />
|
||||
<ContentItems items={menu.items as any} />
|
||||
<ContentItems store={store} items={menu.items as any} />
|
||||
</ApiContentWrap>
|
||||
<BackgroundStub />
|
||||
</RedocWrap>
|
||||
|
|
|
@ -67,18 +67,16 @@ export class SecurityRequirement extends React.PureComponent<SecurityRequirement
|
|||
const security = this.props.security;
|
||||
return (
|
||||
<SecurityRequirementOrWrap>
|
||||
{security.schemes.map(scheme => {
|
||||
return (
|
||||
<SecurityRequirementAndWrap key={scheme.id}>
|
||||
<Link to={scheme.sectionId}>{scheme.id}</Link>
|
||||
{scheme.scopes.length > 0 && ' ('}
|
||||
{scheme.scopes.map(scope => (
|
||||
<ScopeName key={scope}>{scope}</ScopeName>
|
||||
))}
|
||||
{scheme.scopes.length > 0 && ') '}
|
||||
</SecurityRequirementAndWrap>
|
||||
);
|
||||
})}
|
||||
{security.schemes.map(scheme => (
|
||||
<SecurityRequirementAndWrap key={scheme.id}>
|
||||
<Link to={scheme.sectionId}>{scheme.id}</Link>
|
||||
{scheme.scopes.length > 0 && ' ('}
|
||||
{scheme.scopes.map(scope => (
|
||||
<ScopeName key={scope}>{scope}</ScopeName>
|
||||
))}
|
||||
{scheme.scopes.length > 0 && ') '}
|
||||
</SecurityRequirementAndWrap>
|
||||
))}
|
||||
</SecurityRequirementOrWrap>
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user