Skip to content

Commit

Permalink
Merge pull request #1010 from rust-lang/parse-responses
Browse files Browse the repository at this point in the history
Parse the HTTP responses instead of assuming they are valid
  • Loading branch information
shepmaster authored Dec 1, 2023
2 parents ac0aeb9 + 04051ca commit 7b99a67
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 29 deletions.
4 changes: 2 additions & 2 deletions ui/frontend/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,13 @@ export const reExecuteWithBacktrace = (): ThunkAction => dispatch => {

type FetchArg = Parameters<typeof fetch>[0];

export function jsonGet(url: FetchArg) {
export function jsonGet(url: FetchArg): Promise<unknown> {
return fetchJson(url, {
method: 'get',
});
}

export function jsonPost<T>(url: FetchArg, body: Record<string, any>): Promise<T> {
export function jsonPost(url: FetchArg, body: Record<string, any>): Promise<unknown> {
return fetchJson(url, {
method: 'post',
body: JSON.stringify(body),
Expand Down
19 changes: 11 additions & 8 deletions ui/frontend/compileActions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { AsyncThunk, createAsyncThunk } from '@reduxjs/toolkit';
import * as z from 'zod';

import { SimpleThunkAction, adaptFetchError, jsonPost, routes } from './actions';
import { compileRequestPayloadSelector } from './selectors';
Expand All @@ -17,11 +18,12 @@ interface CompileRequestBody {
processAssembly: string;
}

interface CompileResponseBody {
code: string;
stdout: string;
stderr: string;
}
const CompileResponseBody = z.object({
code: z.string(),
stdout: z.string(),
stderr: z.string(),
});
type CompileResponseBody = z.infer<typeof CompileResponseBody>;

interface Props {
sliceName: string;
Expand All @@ -34,9 +36,10 @@ interface CompileActions {
}

export const makeCompileActions = ({ sliceName, target }: Props): CompileActions => {
const action = createAsyncThunk(sliceName, async (payload: CompileRequestBody) =>
adaptFetchError(() => jsonPost<CompileResponseBody>(routes.compile, payload)),
);
const action = createAsyncThunk(sliceName, async (payload: CompileRequestBody) => {
const d = await adaptFetchError(() => jsonPost(routes.compile, payload));
return CompileResponseBody.parseAsync(d);
});

const performCompile = (): SimpleThunkAction => (dispatch, getState) => {
const state = getState();
Expand Down
20 changes: 11 additions & 9 deletions ui/frontend/reducers/output/execute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,18 @@ export interface ExecuteRequestBody {
backtrace: boolean;
}

interface ExecuteResponseBody {
success: boolean;
exitDetail: string;
stdout: string;
stderr: string;
}
const ExecuteResponseBody = z.object({
success: z.boolean(),
exitDetail: z.string(),
stdout: z.string(),
stderr: z.string(),
});
type ExecuteResponseBody = z.infer<typeof ExecuteResponseBody>;

export const performExecute = createAsyncThunk(sliceName, async (payload: ExecuteRequestBody) =>
adaptFetchError(() => jsonPost<ExecuteResponseBody>(routes.execute, payload)),
);
export const performExecute = createAsyncThunk(sliceName, async (payload: ExecuteRequestBody) => {
const d = await adaptFetchError(() => jsonPost(routes.execute, payload));
return ExecuteResponseBody.parseAsync(d);
});

const prepareWithCurrentSequenceNumber = <P>(payload: P, sequenceNumber: number) => ({
payload,
Expand Down
24 changes: 14 additions & 10 deletions ui/frontend/reducers/output/gist.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Draft, PayloadAction, createAsyncThunk, createSlice } from '@reduxjs/toolkit';
import * as z from 'zod';

import { jsonGet, jsonPost, routes } from '../../actions';
import { adaptFetchError, jsonGet, jsonPost, routes } from '../../actions';
import { baseUrlSelector, codeSelector } from '../../selectors';
import RootState from '../../state';
import { Channel, Edition, Mode } from '../../types';
Expand Down Expand Up @@ -39,11 +40,12 @@ type PerformGistLoadProps = Pick<
Exclude<keyof SuccessProps, 'url' | 'code' | 'stdout' | 'stderr'>
>;

interface GistResponseBody {
id: string;
url: string;
code: string;
}
const GistResponseBody = z.object({
id: z.string(),
url: z.string(),
code: z.string(),
});
type GistResponseBody = z.infer<typeof GistResponseBody>;

export const performGistLoad = createAsyncThunk<
SuccessProps,
Expand All @@ -55,8 +57,9 @@ export const performGistLoad = createAsyncThunk<
const gistUrl = new URL(routes.meta.gistLoad, baseUrl);
const u = new URL(id, gistUrl);

const gist = await jsonGet(u);
return { channel, mode, edition, ...gist };
const d = await adaptFetchError(() => jsonGet(u));
const gist = await GistResponseBody.parseAsync(d);
return { ...gist, channel, mode, edition, stdout: '', stderr: '' };
});

export const performGistSave = createAsyncThunk<SuccessProps, void, { state: RootState }>(
Expand All @@ -71,8 +74,9 @@ export const performGistSave = createAsyncThunk<SuccessProps, void, { state: Roo
},
} = state;

const json = await jsonPost<GistResponseBody>(routes.meta.gistSave, { code });
return { ...json, code, stdout, stderr, channel, mode, edition };
const d = await adaptFetchError(() => jsonPost(routes.meta.gistSave, { code }));
const gist = await GistResponseBody.parseAsync(d);
return { ...gist, code, stdout, stderr, channel, mode, edition };
},
);

Expand Down

0 comments on commit 7b99a67

Please sign in to comment.