Skip to content

Commit

Permalink
fix getSurt in case of %-encoded query arg that has no value, eg:
Browse files Browse the repository at this point in the history
'&x^' kept as '&x%5E' while '&x^=' kept as '&x%5E='
fixes #70
  • Loading branch information
ikreymer committed Aug 19, 2024
1 parent 7715994 commit 0a34bcd
Show file tree
Hide file tree
Showing 12 changed files with 54 additions and 33 deletions.
12 changes: 6 additions & 6 deletions dist/cli.cjs

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dist/cli.js

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions dist/index.all.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.all.js.map

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions dist/index.cjs

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions dist/index.js

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/node/index.cjs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions dist/node/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/utils.cjs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
"use strict";var p=Object.defineProperty;var A=Object.getOwnPropertyDescriptor;var S=Object.getOwnPropertyNames;var b=Object.prototype.hasOwnProperty;var _=(t,r)=>{for(var n in r)p(t,n,{get:r[n],enumerable:!0})},R=(t,r,n,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of S(r))!b.call(t,i)&&i!==n&&p(t,i,{get:()=>r[i],enumerable:!(o=A(r,i))||o.enumerable});return t};var P=t=>R(p({},"__esModule",{value:!0}),t);var C={};_(C,{appendRequestQuery:()=>y,concatChunks:()=>x,getSurt:()=>d,jsonToQueryParams:()=>l,jsonToQueryString:()=>u,mfdToQueryParams:()=>g,mfdToQueryString:()=>h,postToGetUrl:()=>w,splitChunk:()=>U});module.exports=P(C);function m(t){let r;typeof t=="string"?r=t:t&&t.length?r=t.reduce((n,o)=>(n+=String.fromCharCode(o),n),""):t?r=t.toString():r="";try{return"__wb_post_data="+btoa(r)}catch{return"__wb_post_data="}}function $(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function d(t){try{if(!t.startsWith("https:")&&!t.startsWith("http:"))return t;t=t.replace(/^(https?:\/\/)www\d*\./,"$1");let r=t.toLowerCase(),n=new URL(r),i=n.hostname.split(".").reverse().join(",");if(n.port&&(i+=":"+n.port),i+=")",i+=n.pathname,n.search){n.searchParams.sort(),i+=n.search;for(let[a,e]of n.searchParams.entries())if(!e){let s=new RegExp(`(?<=[&?])${$(a)}=(?=&|$)`);s.exec(r)||(i=i.replace(s,a))}}return i}catch{return t}}function w(t){let{method:r,headers:n,postData:o}=t;if(r==="GET")return!1;let i=(n.get("content-type")||"").split(";")[0];function a(s){return s instanceof Uint8Array&&(s=new TextDecoder().decode(s)),s}let e="";switch(i){case"application/x-www-form-urlencoded":e=a(o);break;case"application/json":e=u(a(o));break;case"text/plain":try{e=u(a(o),!1)}catch{e=m(o)}break;case"multipart/form-data":{let s=n.get("content-type");if(!s)throw new Error("utils cannot call postToGetURL when missing content-type header");e=h(a(o),s);break}default:e=m(o)}return e!==null?(t.url=y(t.url,e,t.method),t.method="GET",t.requestBody=e,!0):!1}function y(t,r,n){if(!n)return t;let o=t.indexOf("?")>0?"&":"?";return`${t}${o}__wb_method=${n}&${r}`}function l(t,r=!0){if(typeof t=="string")try{t=JSON.parse(t)}catch{t={}}let n=new URLSearchParams,o={},i=e=>n.has(e)?(e in o||(o[e]=1),e+"."+ ++o[e]+"_"):e,a=(e,s="")=>{let f="";if(typeof e=="object"&&!(e instanceof Array))try{for(let[c,T]of Object.entries(e))a(T,c)}catch{e===null&&(f="null")}else if(e instanceof Array)for(let c=0;c<e.length;c++)a(e[c],s);["string","number","boolean"].includes(typeof e)&&(f=e.toString()),f&&n.set(i(s),f)};try{a(t)}catch(e){if(!r)throw e}return n}function g(t,r){let n=new URLSearchParams;t instanceof Uint8Array&&(t=new TextDecoder().decode(t));try{let o=r.split("boundary=")[1],i=t.split(new RegExp("-*"+o+"-*","mi"));for(let a of i){let e=a.trim().match(/name="([^"]+)"\r\n\r\n(.*)/im);e&&n.set(e[1],e[2])}}catch{}return n}function u(t,r=!0){return l(t,r).toString()}function h(t,r){return g(t,r).toString()}function x(t,r){if(t.length===1)return t[0];let n=new Uint8Array(r),o=0;for(let i of t)n.set(i,o),o+=i.byteLength;return n}function U(t,r){return[t.slice(0,r),t.slice(r)]}0&&(module.exports={appendRequestQuery,concatChunks,getSurt,jsonToQueryParams,jsonToQueryString,mfdToQueryParams,mfdToQueryString,postToGetUrl,splitChunk});
"use strict";var p=Object.defineProperty;var S=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var R=Object.prototype.hasOwnProperty;var _=(t,r)=>{for(var n in r)p(t,n,{get:r[n],enumerable:!0})},$=(t,r,n,o)=>{if(r&&typeof r=="object"||typeof r=="function")for(let i of b(r))!R.call(t,i)&&i!==n&&p(t,i,{get:()=>r[i],enumerable:!(o=S(r,i))||o.enumerable});return t};var P=t=>$(p({},"__esModule",{value:!0}),t);var E={};_(E,{appendRequestQuery:()=>y,concatChunks:()=>U,getSurt:()=>w,jsonToQueryParams:()=>l,jsonToQueryString:()=>u,mfdToQueryParams:()=>g,mfdToQueryString:()=>h,postToGetUrl:()=>x,splitChunk:()=>T});module.exports=P(E);function m(t){let r;typeof t=="string"?r=t:t&&t.length?r=t.reduce((n,o)=>(n+=String.fromCharCode(o),n),""):t?r=t.toString():r="";try{return"__wb_post_data="+btoa(r)}catch{return"__wb_post_data="}}function d(t){return t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function w(t){try{if(!t.startsWith("https:")&&!t.startsWith("http:"))return t;t=t.replace(/^(https?:\/\/)www\d*\./,"$1");let r=t.toLowerCase(),n=new URL(r),i=n.hostname.split(".").reverse().join(",");if(n.port&&(i+=":"+n.port),i+=")",i+=n.pathname,n.search){n.searchParams.sort(),i+=n.search;for(let[a,e]of n.searchParams.entries())if(!e){let s=encodeURIComponent(a),f=new RegExp(`(?<=[&?])${d(a)}=(?=&|$)`);if(!f.exec(r)){let c=a===s?f:new RegExp(`(?<=[&?])${d(s)}=(?=&|$)`);i=i.replace(c,s)}}}return i}catch{return t}}function x(t){let{method:r,headers:n,postData:o}=t;if(r==="GET")return!1;let i=(n.get("content-type")||"").split(";")[0];function a(s){return s instanceof Uint8Array&&(s=new TextDecoder().decode(s)),s}let e="";switch(i){case"application/x-www-form-urlencoded":e=a(o);break;case"application/json":e=u(a(o));break;case"text/plain":try{e=u(a(o),!1)}catch{e=m(o)}break;case"multipart/form-data":{let s=n.get("content-type");if(!s)throw new Error("utils cannot call postToGetURL when missing content-type header");e=h(a(o),s);break}default:e=m(o)}return e!==null?(t.url=y(t.url,e,t.method),t.method="GET",t.requestBody=e,!0):!1}function y(t,r,n){if(!n)return t;let o=t.indexOf("?")>0?"&":"?";return`${t}${o}__wb_method=${n}&${r}`}function l(t,r=!0){if(typeof t=="string")try{t=JSON.parse(t)}catch{t={}}let n=new URLSearchParams,o={},i=e=>n.has(e)?(e in o||(o[e]=1),e+"."+ ++o[e]+"_"):e,a=(e,s="")=>{let f="";if(typeof e=="object"&&!(e instanceof Array))try{for(let[c,A]of Object.entries(e))a(A,c)}catch{e===null&&(f="null")}else if(e instanceof Array)for(let c=0;c<e.length;c++)a(e[c],s);["string","number","boolean"].includes(typeof e)&&(f=e.toString()),f&&n.set(i(s),f)};try{a(t)}catch(e){if(!r)throw e}return n}function g(t,r){let n=new URLSearchParams;t instanceof Uint8Array&&(t=new TextDecoder().decode(t));try{let o=r.split("boundary=")[1],i=t.split(new RegExp("-*"+o+"-*","mi"));for(let a of i){let e=a.trim().match(/name="([^"]+)"\r\n\r\n(.*)/im);e&&n.set(e[1],e[2])}}catch{}return n}function u(t,r=!0){return l(t,r).toString()}function h(t,r){return g(t,r).toString()}function U(t,r){if(t.length===1)return t[0];let n=new Uint8Array(r),o=0;for(let i of t)n.set(i,o),o+=i.byteLength;return n}function T(t,r){return[t.slice(0,r),t.slice(r)]}0&&(module.exports={appendRequestQuery,concatChunks,getSurt,jsonToQueryParams,jsonToQueryString,mfdToQueryParams,mfdToQueryString,postToGetUrl,splitChunk});
2 changes: 1 addition & 1 deletion dist/utils.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 10 additions & 1 deletion src/lib/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,18 @@ export function getSurt(url: string) {
surt += urlObj.search;
for (const [key, value] of urlObj.searchParams.entries()) {
if (!value) {
// if no value set, by default the surt contains 'key='
// however, for compatibility, only want to add a trailing '='
// if original URL has it.
const keyEncoded = encodeURIComponent(key);
const rx = new RegExp(`(?<=[&?])${rxEscape(key)}=(?=&|$)`);
// if original URL does *not* have trailing '=', attempt to remove it below
if (!rx.exec(urlLower)) {
surt = surt.replace(rx, key);
// use URI encoded version to match the query arg if key is %-encoded
const rxEncoded = (
key === keyEncoded ?
rx : new RegExp(`(?<=[&?])${rxEscape(keyEncoded)}=(?=&|$)`));
surt = surt.replace(rxEncoded, keyEncoded);
}
}
}
Expand Down
12 changes: 12 additions & 0 deletions test/testUtils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,4 +137,16 @@ describe("utils", () => {
"com,example)/some/path?*&a=b&c=d&z"
);
});

test("surt with %-encoded query, trailing = param", () => {
expect(getSurt("https://www.example.com/some/path?a=b&c=d&e^=&z")).toBe(
"com,example)/some/path?a=b&c=d&e%5E=&z"
);
});
test("surt with %-encoded query, no trailing = param", () => {
expect(getSurt("https://www.example.com/some/path?a=b&c=d&e^&z")).toBe(
"com,example)/some/path?a=b&c=d&e%5E&z"
);
});

});

0 comments on commit 0a34bcd

Please sign in to comment.