dsh-read-url 1.1.0 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-read-url",
3
- "version": "1.1.0",
4
- "description": "DeepSeek Harness URL reader: fetch any webpage (HTML/JSON/RSS/Atom), auto-detect encoding (UTF-16 BOM/GBK/Big5/Shift-JIS), extract clean main content with auto-pagination, output compact text/Markdown to save tokens. Zero runtime dependencies, no API key, drop-in.",
3
+ "version": "1.3.1",
4
+ "description": "DeepSeek Harness URL reader: fetch any webpage (HTML/JSON/RSS/Atom), auto-detect encoding (UTF-16 BOM/GBK/Big5/Shift-JIS), extract clean main content with auto-pagination, output compact text/Markdown to save tokens. Zero runtime dependencies, no API key, drop-in. Follows meta-refresh shells, reads JSON-LD metadata, honors base href.",
5
5
  "type": "module",
6
6
  "main": "index.js",
7
7
  "files": [
package/proxy-fallback.js CHANGED
@@ -97,7 +97,11 @@ export async function fetchViaCurlProxy(url, cfg, externalSignal, proxyOverride)
97
97
  '--max-filesize', String(cfg.maxBytes), // unit is BYTES, not KB
98
98
  '-x', proxy,
99
99
  '-A', cfg.userAgent,
100
- '-w', '\n%{http_code} %{content_type}',
100
+ // trailing metadata line: "<code> <content_type> <url_effective>"
101
+ // (url_effective last: content_type may be empty, URLs never contain
102
+ // unencoded spaces — parse from both ends so the final URL of a redirect
103
+ // chain survives).
104
+ '-w', '\n%{http_code} %{content_type} %{url_effective}',
101
105
  url,
102
106
  ]
103
107
  try {
@@ -107,14 +111,16 @@ export async function fetchViaCurlProxy(url, cfg, externalSignal, proxyOverride)
107
111
  resolve(stdout)
108
112
  })
109
113
  })
110
- // tail line carries the metadata: "<http_code> <content_type>"
114
+ // tail line carries the metadata: "<code> <content_type> <url_effective>"
111
115
  const nl = buf.lastIndexOf(0x0a)
112
116
  if (nl < 0) return null // no trailing metadata — abnormal response, treat as failure
113
117
  const meta = buf.subarray(nl + 1).toString('latin1').trim()
114
118
  const body = buf.subarray(0, nl)
115
- const [codeStr, ...ctParts] = meta.split(' ')
119
+ const parts = meta.split(' ')
120
+ const codeStr = parts.shift()
121
+ const finalUrlEff = parts.length > 1 ? parts.pop() : url
116
122
  const code = Number(codeStr)
117
- const contentType = ctParts.join(' ')
123
+ const contentType = parts.join(' ')
118
124
  if (code >= 200 && code < 300) {
119
125
  // Headerless responses: gate binary bodies out (same rule as the direct
120
126
  // path — curl writes an empty %{content_type} then).
@@ -126,7 +132,7 @@ export async function fetchViaCurlProxy(url, cfg, externalSignal, proxyOverride)
126
132
  if (contentType && !/text\/html|application\/xhtml|text\/plain|\/json|[+/]xml/i.test(contentType)) {
127
133
  return { error: `Unsupported content-type: ${contentType.split(';')[0]}` }
128
134
  }
129
- return { buffer: body, contentType, finalUrl: url, viaProxy: proxy }
135
+ return { buffer: body, contentType, finalUrl: finalUrlEff, viaProxy: proxy }
130
136
  } catch (err) {
131
137
  // curl error 63 = exceeded --max-filesize (page too large, not a proxy
132
138
  // problem — report it as such instead of "proxy unreachable")