-
Notifications
You must be signed in to change notification settings - Fork 526
Web lab 2 network tab: store request data in redux #70744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
56a1cf6
3b7b7d4
2fb7a0d
82d6449
6f8701d
af2c3ff
6f4ec8d
d5c9b65
ae5b5c5
2968edc
5c01070
f9f5488
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,10 @@ import {MultiFileSource} from '@cdo/apps/lab2/types'; | |
|
|
||
| import {ProjectServiceWorkerMessageType} from './constants'; | ||
| import {generateContentSecurityPolicyForPreview} from './contentSecurityPolicyHelper'; | ||
| import {addBaseTagToDocument} from './htmlParsingHelpers'; | ||
| import { | ||
| addBaseTagToDocument, | ||
| addCSPViolationListenerToDocument, | ||
| } from './htmlParsingHelpers'; | ||
|
|
||
| // Hook that handles registering and communicating with the project service worker. | ||
| function useProjectServiceWorker( | ||
|
|
@@ -94,6 +97,7 @@ function useProjectServiceWorker( | |
| const doc = parser.parseFromString(file.contents, 'text/html'); | ||
| const urlSuffix = folder ? `${folder}/` : ''; | ||
| addBaseTagToDocument(doc, `${window.location.origin}/${urlSuffix}`); | ||
| addCSPViolationListenerToDocument(doc); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Tidy! |
||
| content = doc.documentElement.outerHTML; | ||
| } else if (file.language === 'css') { | ||
| mimeType = 'text/css'; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,8 @@ const PROJECT_SERVICE_WORKER_BROADCAST_CHANNEL = 'weblab2-file-preview'; | |
| const SERVING_HTML_FILE = 'SERVING_HTML_FILE'; | ||
| const RECEIVED_SOURCE = 'RECEIVED_SOURCE'; | ||
| const UPDATE_FILES = 'UPDATE_FILES'; | ||
| const NETWORK_REQUEST = 'NETWORK_REQUEST'; | ||
| const NETWORK_RESPONSE = 'NETWORK_RESPONSE'; | ||
|
|
||
| function main() { | ||
| let filesData = {}; | ||
|
|
@@ -45,7 +47,7 @@ function main() { | |
| }); | ||
|
|
||
| // Intercept fetch requests | ||
| self.addEventListener('fetch', event => { | ||
| self.addEventListener('fetch', async event => { | ||
| const url = new URL(event.request.url); | ||
| let requestedFile = getFilenameFromUrl(url); | ||
| const referrerFile = getFilenameFromUrl(new URL(event.request.referrer)); | ||
|
|
@@ -67,6 +69,50 @@ function main() { | |
| filePath: requestedFile, | ||
| }); | ||
| } | ||
| if (url.origin !== location.origin) { | ||
| const performanceStartTime = performance.now(); | ||
| const startTime = new Date().toLocaleString(); | ||
| const requestId = crypto.randomUUID(); | ||
| let response; | ||
| let performanceEndTime; | ||
| let error; | ||
| broadcastChannel.postMessage({ | ||
| type: NETWORK_REQUEST, | ||
| requestData: { | ||
| url: event.request.url, | ||
| method: event.request.method, | ||
| startTime, | ||
| id: requestId, | ||
| }, | ||
| }); | ||
| try { | ||
| response = await fetch(event.request); | ||
| performanceEndTime = performance.now(); | ||
| } catch (e) { | ||
| error = e; | ||
| } | ||
| let bodyText; | ||
| try { | ||
| bodyText = response ? await response.text() : undefined; | ||
| } catch (e) { | ||
| error = e; | ||
| } | ||
| broadcastChannel.postMessage({ | ||
| type: NETWORK_RESPONSE, | ||
| responseData: { | ||
| url: event.request.url, | ||
| body: bodyText, | ||
| status: response ? response.status : undefined, | ||
| timeElapsed: performanceEndTime | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice! |
||
| ? Math.floor(performanceEndTime - performanceStartTime) | ||
| : undefined, | ||
| error, | ||
| id: requestId, | ||
| contentType: response?.headers?.get('Content-Type'), | ||
| }, | ||
| }); | ||
| return response; | ||
| } | ||
| return; | ||
| } | ||
| }); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,66 @@ | ||
| import {createSlice, PayloadAction} from '@reduxjs/toolkit'; | ||
|
|
||
| import {registerReducers} from '@cdo/apps/redux'; | ||
|
|
||
| export interface NetworkEntry { | ||
| id: string; | ||
| request: RequestData; | ||
| response?: ResponseData; | ||
| } | ||
|
|
||
| interface RequestData { | ||
| method: string; | ||
| startTime: string; | ||
| url: string; | ||
| cspDirectiveViolated?: string; | ||
| } | ||
|
|
||
| interface ResponseData { | ||
| url: string; | ||
| status: number; | ||
| timeElapsed?: number; | ||
| body?: string; | ||
| error?: Error; | ||
| contentType?: string; | ||
| } | ||
|
|
||
| export interface Weblab2NetworkState { | ||
| requests: NetworkEntry[]; | ||
| } | ||
|
|
||
| const initialState: Weblab2NetworkState = { | ||
| requests: [], | ||
| }; | ||
|
|
||
| const networkSlice = createSlice({ | ||
| name: 'network', | ||
| initialState, | ||
| reducers: { | ||
| addRequestData: ( | ||
| state, | ||
| action: PayloadAction<{id: string; request: RequestData}> | ||
| ) => { | ||
| state.requests.push(action.payload); | ||
| }, | ||
| addResponseData: ( | ||
| state, | ||
| action: PayloadAction<{id: string; response: ResponseData}> | ||
| ) => { | ||
| const {id, response} = action.payload; | ||
| const request = state.requests.find(r => r.id === id); | ||
| if (request) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we log if we return a response which doesn't have a corresponding request?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll handle that in the network tab (display an appropriate error). |
||
| request.response = response; | ||
| } | ||
| }, | ||
| clearRequests: state => { | ||
| state.requests = []; | ||
| }, | ||
| }, | ||
| }); | ||
|
|
||
| registerReducers({weblab2Network: networkSlice.reducer}); | ||
|
|
||
| export const {addRequestData, addResponseData, clearRequests} = | ||
| networkSlice.actions; | ||
|
|
||
| export default networkSlice.reducer; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While here, do we still need
updateLinksToNonHtmlFiles?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we don't, but I'll handle that separately.