Skip to content

Commit b6e0f6e

Browse files
authored
Fix expiration parsing, support 'Y' and empty expiration (#49)
1 parent efc882e commit b6e0f6e

File tree

5 files changed

+26
-14
lines changed

5 files changed

+26
-14
lines changed

frontend/index.client.js

+5-2
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ window.addEventListener('DOMContentLoaded', () => {
6868
let customName = '', adminUrl = '', file = null
6969

7070
const NAME_REGEX = /^[a-zA-Z0-9+_\-\[\]*$@,;]{3,}$/
71-
const EXPIRE_REGEX = /^\d+\s*[smhdwM]?$/
71+
const EXPIRE_REGEX = /^\d+\s*[smhdwMY]?$/
7272
const submitButton = $('#submit-button')
7373
const deleteButton = $('#delete-button')
7474
const pasteEditArea = $('#paste-textarea')
@@ -83,7 +83,10 @@ window.addEventListener('DOMContentLoaded', () => {
8383
const pasteNotEmpty = inputType === 'edit'
8484
? pasteEditArea.prop('value').length > 0
8585
: file !== null
86-
const expirationValid = EXPIRE_REGEX.test(expiration) // TODO: verify it
86+
let expirationValid = EXPIRE_REGEX.test(expiration) // TODO: verify it
87+
if (!expiration) {
88+
expirationValid = true
89+
}
8790
const nameValid = urlType !== 'custom' || NAME_REGEX.test(customName)
8891
const adminUrlValid = urlType !== 'admin' || isAdminUrlLegal(adminUrl)
8992

frontend/index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ <h2>Settings</h2>
4343
<div id='paste-expiration-panel' class='paste-setting-subitem-panel'>
4444
<input list='expiration-choices' type='text' min='60' step='1' name='paste-expiration'
4545
id='paste-expiration-input' placeholder='Expiration (secs)' value='7d'>
46-
<label class='small-label' for='paste-expiration-input'>Delete your paste after a period of time. <br>Units: s (seconds), m (minutes), h (hours), d (days), M (months)</label>
46+
<label class='small-label' for='paste-expiration-input'>Delete your paste after a period of time (leave blank for no expiry). <br>Units: s (seconds), m (minutes), h (hours), d (days), M (months), Y (years)</label>
4747
</div>
4848
<div id='paste-passwd-panel' class='paste-setting-subitem-panel'>
4949
<input type='text' spellcheck='false' name='paste-expiration' id='paste-passwd-input' placeholder='Password'>

src/common.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,10 @@ export function parsePath(pathname) {
7575
}
7676

7777
export function parseExpiration(expirationStr) {
78-
const EXPIRE_REGEX = /^[\d\.]+\s*[smhdwM]?$/
78+
if (!expirationStr) {
79+
return NaN
80+
}
81+
const EXPIRE_REGEX = /^[\d\.]+\s*[smhdwMY]?$/
7982
if (!EXPIRE_REGEX.test(expirationStr)) {
8083
throw new WorkerError(400, `‘${expirationStr}’ is not a valid expiration specification`)
8184
}
@@ -86,7 +89,8 @@ export function parseExpiration(expirationStr) {
8689
else if (lastChar === 'h') expirationSeconds *= 3600
8790
else if (lastChar === 'd') expirationSeconds *= 3600 * 24
8891
else if (lastChar === 'w') expirationSeconds *= 3600 * 24 * 7
89-
else if (lastChar === 'M') expirationSeconds *= 3600 * 24 * 7 * 30
92+
else if (lastChar === 'M') expirationSeconds *= 3600 * 24 * 30
93+
else if (lastChar === 'Y') expirationSeconds *= 3600 * 24 * 365
9094
return expirationSeconds
9195
}
9296

src/handlers/handleWrite.js

+10-7
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,21 @@ async function createPaste(env, content, isPrivate, expire, short, createDate, p
2525
}
2626
}
2727

28-
await env.PB.put(short, content, {
29-
expirationTtl: expire,
28+
let options = {
3029
metadata: {
3130
postedAt: createDate,
3231
passwd: passwd,
3332
filename: filename,
3433
lastModified: now,
3534
},
36-
})
35+
}
36+
37+
if (!isNaN(expire)) {
38+
options.expirationTtl = expire
39+
}
40+
41+
await env.PB.put(short, content, options)
42+
3743
let accessUrl = env.BASE_URL + "/" + short
3844
const adminUrl = env.BASE_URL + "/" + short + params.SEP + passwd
3945
return {
@@ -101,10 +107,7 @@ export async function handlePostOrPut(request, env, ctx, isPut) {
101107
let expirationSeconds = undefined
102108
if (expire !== undefined) {
103109
expirationSeconds = parseExpiration(expire)
104-
if (isNaN(expirationSeconds)) {
105-
throw new WorkerError(400, `cannot parse expire ${expirationSeconds} as an number`)
106-
}
107-
if (expirationSeconds < 60) {
110+
if (!isNaN(expirationSeconds) && expirationSeconds < 60) {
108111
throw new WorkerError(
109112
400,
110113
`due to limitation of Cloudflare, expire should be a integer greater than 60, '${expirationSeconds}' given`,

test/basic.spec.js

+4-2
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,10 @@ test("expire", async () => {
127127
await testExpireParse("100m", 6000)
128128
await testExpireParse("100h", 360000)
129129
await testExpireParse("1d", 86400)
130-
await testExpireParse("1M", 18144000)
130+
await testExpireParse("1M", 2592000)
131+
await testExpireParse("1Y", 31536000)
131132
await testExpireParse("100 m", 6000)
133+
await testExpireParse("", null)
132134

133135
const testFailParse = async (expire) => {
134136
const uploadResponse = await workerFetch(new Request(BASE_URL, {
@@ -205,4 +207,4 @@ test("custom passwd", async () => {
205207
expect(putResponseJson["admin"]).toStrictEqual(`${url}:${wrongPasswd}`) // passwd may change
206208
})
207209

208-
// TODO: add tests for CORS
210+
// TODO: add tests for CORS

0 commit comments

Comments
 (0)