Skip to content

Commit 5c7ce09

Browse files
authored
Merge pull request #40 from eviltik/main
return axios errors, trim() response body, skipContentTypeCheck
2 parents 29a6a67 + 4d6a235 commit 5c7ce09

File tree

4 files changed

+62
-16
lines changed

4 files changed

+62
-16
lines changed

src/config.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ const requestOptions = {
99
responseType: 'text',
1010
responseEncoding: 'utf8',
1111
timeout: 6e4, // 1 minute
12-
maxRedirects: 3
12+
maxRedirects: 3,
13+
skipContentTypeCheck: false
1314
}
1415

1516
export const getRequestOptions = () => {

src/main.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ export {
2222

2323
export const read = async (url) => {
2424
const xmldata = await getXML(url)
25-
if (!xmldata) {
26-
throw new Error(`Could not fetch XML content from "${url}"`)
25+
26+
const { xml, error } = xmldata
27+
if (error) {
28+
throw error
2729
}
28-
const { xml } = xmldata
30+
2931
if (!validate(xml)) {
3032
throw new Error(`Failed while validating XML format from "${url}"`)
3133
}
34+
3235
info('Parsing XML data...')
3336
const jsonObj = xml2obj(xml)
3437
return isRSS(jsonObj) ? parseRSS(jsonObj) : isAtom(jsonObj) ? parseAtom(jsonObj) : null

src/utils/retrieve.js

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,49 @@ import logger from './logger.js'
66

77
import { getRequestOptions } from '../config.js'
88

9+
const acceptedContentTypes = [
10+
'text/xml',
11+
'application/xml',
12+
'application/atom+xml',
13+
'application/rss+xml',
14+
'application/x-rss+xml'
15+
]
16+
917
export default async (url) => {
18+
if (typeof url !== 'string') {
19+
const error = new Error('url should be a string')
20+
return { error }
21+
}
22+
23+
const skipContentTypeCheck = getRequestOptions().skipContentTypeCheck || false
24+
1025
try {
1126
const res = await axios.get(url, getRequestOptions())
1227

13-
const contentType = res.headers['content-type'] || ''
14-
if (!contentType || !contentType.includes('xml')) {
15-
logger.error(`Got invalid content-type (${contentType}) from "${url}"`)
16-
return null
28+
let contentType = res.headers['content-type'] || ''
29+
// text/xml;charset= ..
30+
contentType = contentType.split(';')[0]
31+
32+
if (!skipContentTypeCheck) {
33+
if (!contentType || acceptedContentTypes.indexOf(contentType) === -1) {
34+
logger.error(`Got invalid content-type (${contentType}) from "${url}"`)
35+
const error = new Error(`invalid content-type (${contentType}) from "${url}"`)
36+
return { error }
37+
}
38+
}
39+
40+
if (res.data === undefined) {
41+
const error = new Error('something wrong append with axios')
42+
return { error }
1743
}
44+
1845
const result = {
1946
url,
20-
xml: res.data
47+
xml: res.data.trim()
2148
}
2249
return result
23-
} catch (err) {
24-
logger.error(err.message || err)
25-
return null
50+
} catch (error) {
51+
logger.error(error.message || error)
52+
return { error }
2653
}
2754
}

src/utils/retrieve.test.js

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,39 @@ test('test retrieve from good source', async () => {
2424
expect(result.xml).toBe('<div>this is content</div>')
2525
})
2626

27-
test('test retrieve with invalid content type', async () => {
27+
test('test retrieve from good source, but having \\r\\n before/after root xml', async () => {
28+
const url = 'https://some.where/good/page'
29+
const { baseUrl, path } = parseUrl(url)
30+
nock(baseUrl).head(path).reply(200)
31+
nock(baseUrl).get(path).reply(200, '\n\r\r\n\n<div>this is content</div>\n\r\r\n\n', {
32+
'Content-Type': 'application/xml'
33+
})
34+
const result = await retrieve(url)
35+
expect(result.xml).toBe('<div>this is content</div>')
36+
})
37+
38+
test('test retrieve with invalid response content type', async () => {
2839
const url = 'https://some.where/bad/page'
2940
const { baseUrl, path } = parseUrl(url)
3041
nock(baseUrl).head(path).reply(200)
3142
nock(baseUrl).get(path).reply(200, '', {
3243
'Content-Type': 'something/strange'
3344
})
3445
const result = await retrieve(url)
35-
expect(result).toBe(null)
46+
expect(typeof result).toBe('object')
47+
expect(typeof result.error).toBe('object')
48+
expect(typeof result.error.message).toBe('string')
3649
})
3750

38-
test('test retrieve with invalid status', async () => {
51+
test('test retrieve with invalid response status code', async () => {
3952
const url = 'https://some.where/bad/page'
4053
const { baseUrl, path } = parseUrl(url)
4154
nock(baseUrl).head(path).reply(500)
4255
nock(baseUrl).get(path).reply(500, '<xml><message>Error 500</message></xml>', {
4356
'Content-Type': 'application/xml'
4457
})
4558
const result = await retrieve(url)
46-
expect(result).toBe(null)
59+
expect(typeof result).toBe('object')
60+
expect(typeof result.error).toBe('object', result.error)
61+
expect(typeof result.error.message).toBe('string')
4762
})

0 commit comments

Comments
 (0)