Skip to content

Commit

Permalink
feature: read file for electron iframe preview (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
levivilet authored Aug 31, 2024
1 parent 2c1d2d9 commit 036bd5f
Show file tree
Hide file tree
Showing 11 changed files with 160 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const value = 'require-corp'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const value = 'cross-origin'
6 changes: 6 additions & 0 deletions src/parts/FileSystem/FileSystem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as nodeFs from 'node:fs/promises'

export const readFile = async (url: string) => {
const buffer = await nodeFs.readFile(url)
return buffer
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const getPathName = (url: string) => {
try {
const p = new URL(url).pathname
return p
} catch {
return ''
}
}

export const getElectronFileResponseAbsolutePath = (url: string) => {
// TODO support windows paths
// TODO disallow dot dot in paths
const pathName = getPathName(url)
if (pathName.endsWith('/')) {
return pathName + 'index.html'
}
return pathName
}
18 changes: 18 additions & 0 deletions src/parts/GetHeaders/GetHeaders.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { extname } from 'node:path'
import * as CrossOriginEmbedderPolicy from '../CrossOriginEmbedderPolicy/CrossOriginEmbedderPolicy.ts'
import * as CrossOriginResourcePolicy from '../CrossOriginResourcePolicy/CrossOriginResourcePolicy.ts'
import * as GetMimeType from '../GetMimeType/GetMimeType.ts'
import * as HttpHeader from '../HttpHeader/HttpHeader.ts'

export const getHeaders = (absolutePath: string) => {
const extension = extname(absolutePath)
const mime = GetMimeType.getMimeType(extension)
const headers = {
[HttpHeader.ContentType]: mime,
[HttpHeader.CrossOriginResourcePolicy]: CrossOriginResourcePolicy.value,
[HttpHeader.CrossOriginEmbedderPolicy]: CrossOriginEmbedderPolicy.value,
}
return {
...headers,
}
}
28 changes: 28 additions & 0 deletions src/parts/GetMimeType/GetMimeType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import * as MimeType from '../MimeType/MimeType.ts'

export const getMimeType = (fileExtension: string) => {
switch (fileExtension) {
case '.html':
return MimeType.TextHtml
case '.css':
return MimeType.TextCss
case '.ttf':
return MimeType.FontTtf
case '.js':
case '.mjs':
case '.ts':
return MimeType.TextJavaScript
case '.svg':
return MimeType.ImageSvgXml
case '.png':
return MimeType.ImagePng
case '.json':
case '.map':
return MimeType.ApplicationJson
case '.mp3':
return MimeType.AudioMpeg
default:
console.warn(`unsupported file extension: ${fileExtension}`)
return ''
}
}
8 changes: 8 additions & 0 deletions src/parts/HttpHeader/HttpHeader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export const CacheControl = 'Cache-Control'
export const ContentType = 'Content-Type'
export const ContentSecurityPolicy = 'Content-Security-Policy'
export const CrossOriginEmbedderPolicy = 'Cross-Origin-Embedder-Policy'
export const CrossOriginOpenerPolicy = 'Cross-Origin-Opener-Policy'
export const CrossOriginResourcePolicy = 'Cross-Origin-Resource-Policy'
export const Etag = 'Etag'
export const IfNotMatch = 'if-none-match'
1 change: 1 addition & 0 deletions src/parts/HttpStatusCode/HttpStatusCode.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export const MethodNotAllowed = 405
export const NotFound = 404
export const Ok = 200
37 changes: 37 additions & 0 deletions src/parts/MimeType/MimeType.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export const ApplicationFontWoff = 'application/font-woff'
export const ApplicationJson = 'application/json'
export const AudioMidi = 'audio/midi'
export const AudioMpeg = 'audio/mpeg'
export const AudioOgg = 'audio/ogg'
export const AudioOpus = 'audio/opus'
export const AudioXaac = 'audio/x-aac'
export const AudioXMsWma = 'audio/x-ms-wma'
export const AudioXWav = 'audio/x-wav'
export const FontTtf = 'font/ttf'
export const ImageAvif = 'image/avif'
export const ImageBmp = 'image/bmp'
export const ImageGif = 'image/gif'
export const ImageJpg = 'image/jpg'
export const ImagePng = 'image/png'
export const ImageSvgXml = 'image/svg+xml'
export const ImageTiff = 'image/tiff'
export const ImageVndAdobePhotoShop = 'image/vnd.adobe.photoshop'
export const ImageWebp = 'image/webp'
export const ImageXIcon = 'image/x-icon'
export const ImageXTga = 'image/x-tga'
export const TextCalendar = 'text/calendar'
export const TextCss = 'text/css'
export const TextCvs = 'text/csv'
export const TextHtml = 'text/html'
export const TextJavaScript = 'text/javascript'
export const TextPlain = 'text/plain'
export const TextXml = 'text/xml'
export const VideoMp4 = 'video/mp4'
export const VideoMpeg = 'video/mpeg'
export const VideoQuickTime = 'video/quicktime'
export const VideoWebm = 'video/webm'
export const VideoXFlv = 'video/x-flv'
export const VideoXMatroska = 'video/x-matroska'
export const VideoXMsVideo = 'video/x-msvideo'
export const VideoXMsWmv = 'video/x-ms-wmv'
export const VideoXSgiMovie = 'video/x-sgi-movie'
34 changes: 24 additions & 10 deletions src/parts/WebViewProtocol/WebViewProtocol.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,42 @@
import * as FileSystem from '../FileSystem/FileSystem.ts'
import * as GetElectronFileResponseAbsolutePath from '../GetElectronFileResponseAbsolutePath/GetElectronFileResponseAbsolutePath.ts'
import * as GetHeaders from '../GetHeaders/GetHeaders.ts'
import * as HttpMethod from '../HttpMethod/HttpMethod.ts'
import * as HttpStatusCode from '../HttpStatusCode/HttpStatusCode.ts'

export const getResponse = (method: string, url: string) => {
const defaultHeaders = {
'Cross-Origin-Resource-Policy': 'cross-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
}

export const getResponse = async (method: string, url: string) => {
// TODO allow head requests
if (method !== HttpMethod.Get) {
return {
body: 'Method not allowed',
init: {
status: HttpStatusCode.MethodNotAllowed,
headers: {
'Cross-Origin-Resource-Policy': 'cross-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
headers: defaultHeaders,
},
}
}
const absolutePath = GetElectronFileResponseAbsolutePath.getElectronFileResponseAbsolutePath(url)
if (!absolutePath) {
return {
body: 'not found',
init: {
status: HttpStatusCode.NotFound,
headers: defaultHeaders,
},
}
}
const content = await FileSystem.readFile(absolutePath)
const headers = GetHeaders.getHeaders(absolutePath)
return {
body: 'test 123',
body: content,
init: {
status: HttpStatusCode.Ok,
headers: {
'Cross-Origin-Resource-Policy': 'cross-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
headers,
},
}
}
22 changes: 18 additions & 4 deletions test/WebViewProtocol.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
import { expect, test } from '@jest/globals'
import { beforeEach, expect, jest, test } from '@jest/globals'
import * as HttpMethod from '../src/parts/HttpMethod/HttpMethod.ts'
import * as HttpStatusCode from '../src/parts/HttpStatusCode/HttpStatusCode.ts'
import * as WebViewProtocol from '../src/parts/WebViewProtocol/WebViewProtocol.ts'

beforeEach(() => {
jest.resetAllMocks()
})

jest.unstable_mockModule('../src/parts/FileSystem/FileSystem.ts', () => {
return {
readFile: jest.fn(),
}
})

const WebViewProtocol = await import('../src/parts/WebViewProtocol/WebViewProtocol.ts')
const FileSystem = await import('../src/parts/FileSystem/FileSystem.ts')

test('method not allowed - post', async () => {
const method = HttpMethod.Post
Expand All @@ -20,12 +32,14 @@ test('method not allowed - post', async () => {

test('get', async () => {
const method = HttpMethod.Get
const url = '/test/media'
const url = 'lvce-webview://-/test/media/'
jest.spyOn(FileSystem, 'readFile').mockResolvedValue(Buffer.from('a'))
expect(await WebViewProtocol.getResponse(method, url)).toEqual({
body: 'test 123',
body: Buffer.from('a'),
init: {
status: HttpStatusCode.Ok,
headers: {
'Content-Type': 'text/html',
'Cross-Origin-Resource-Policy': 'cross-origin',
'Cross-Origin-Embedder-Policy': 'require-corp',
},
Expand Down

0 comments on commit 036bd5f

Please sign in to comment.