forked from akai/readest
fix(opds): workaround parsing of encoded params in proxied url in cloudflare (#2575)
This commit is contained in:
@@ -1,7 +1,18 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
|
||||
async function handleRequest(request: NextRequest, method: 'GET' | 'HEAD') {
|
||||
const url = request.nextUrl.searchParams.get('url');
|
||||
// Cloudflare Workers incorrectly decodes %26 to & in the url parameter value,
|
||||
// causing query parameters within the proxied URL (like &start_index=26) to be
|
||||
// treated as separate top-level parameters instead of part of the url value.
|
||||
// We work around this by manually extracting the url parameter - capturing everything
|
||||
// from 'url=' until we hit our known parameters (&stream= or &auth=), then decoding it.
|
||||
const fullUrl = request.url;
|
||||
const urlParamStart = fullUrl.indexOf('url=') + 4;
|
||||
const streamParam = fullUrl.lastIndexOf('&stream=');
|
||||
const authParam = fullUrl.lastIndexOf('&auth=');
|
||||
const urlParamEnd = Math.min(...[streamParam, authParam].filter((i) => i > 0), fullUrl.length);
|
||||
const encodedUrl = fullUrl.substring(urlParamStart, urlParamEnd);
|
||||
const url = decodeURIComponent(encodedUrl);
|
||||
const auth = request.nextUrl.searchParams.get('auth');
|
||||
const stream = request.nextUrl.searchParams.get('stream');
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ export function CatalogManager() {
|
||||
<div className='min-w-0 flex-1'>
|
||||
<div className='mb-1 flex items-center justify-between'>
|
||||
<h3 className='card-title truncate text-sm'>
|
||||
{catalog.icon && <span className='mr-2'>{catalog.icon}</span>}
|
||||
{catalog.icon && <span className=''>{catalog.icon}</span>}
|
||||
{catalog.name}
|
||||
</h3>
|
||||
<button
|
||||
@@ -226,7 +226,7 @@ export function CatalogManager() {
|
||||
>
|
||||
<div className='card-body p-4'>
|
||||
<h3 className='card-title mb-1 text-sm'>
|
||||
{catalog.icon && <span className='mr-2'>{catalog.icon}</span>}
|
||||
{catalog.icon && <span className=''>{catalog.icon}</span>}
|
||||
{catalog.name}
|
||||
</h3>
|
||||
{catalog.description && (
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useMemo } from 'react';
|
||||
import { groupByArray } from './utils/opdsUtils';
|
||||
import { CachedImage } from '@/components/CachedImage';
|
||||
import { OPDSPublication, REL } from '@/types/opds';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
|
||||
interface PublicationCardProps {
|
||||
publication: OPDSPublication;
|
||||
@@ -20,6 +21,7 @@ export function PublicationCard({
|
||||
resolveURL,
|
||||
onGenerateCachedImageUrl,
|
||||
}: PublicationCardProps) {
|
||||
const _ = useTranslation();
|
||||
const linksByRel = useMemo(
|
||||
() => groupByArray(publication.links, (link) => link.rel),
|
||||
[publication.links],
|
||||
@@ -55,9 +57,10 @@ export function PublicationCard({
|
||||
return `${currency} ${value}`;
|
||||
}
|
||||
if (linksByRel.has(REL.ACQ + '/open-access')) {
|
||||
return 'Open Access';
|
||||
return _('Open Access');
|
||||
}
|
||||
return null;
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [publication.links, linksByRel]);
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user