Skip to content
This repository was archived by the owner on Dec 15, 2022. It is now read-only.

Commit b7a8890

Browse files
author
Winston Liu
authored
Merge pull request #1065 from atom/wl-ensure-json
Make sure body was successfully parsed as JSON before filtering
2 parents 7acc380 + 9c82f20 commit b7a8890

2 files changed

Lines changed: 50 additions & 23 deletions

File tree

lib/atom-io-client.coffee

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,19 +69,25 @@ class AtomIoClient
6969
options = {
7070
url: "#{@baseURL}#{path}"
7171
headers: {'User-Agent': navigator.userAgent}
72-
json: true
7372
gzip: true
7473
}
7574

7675
request options, (err, res, body) =>
7776
return callback(err) if err
7877

79-
delete body.versions
80-
cached =
81-
data: body
82-
createdOn: Date.now()
83-
localStorage.setItem(@cacheKeyForPath(path), JSON.stringify(cached))
84-
callback(err, cached.data)
78+
try
79+
# NOTE: request's json option does not populate err if parsing fails,
80+
# so we do it manually
81+
body = JSON.parse(body)
82+
delete body.versions
83+
84+
cached =
85+
data: body
86+
createdOn: Date.now()
87+
localStorage.setItem(@cacheKeyForPath(path), JSON.stringify(cached))
88+
callback(err, cached.data)
89+
catch error
90+
callback(error)
8591

8692
cacheKeyForPath: (path) ->
8793
"settings-view:#{path}"
@@ -199,7 +205,6 @@ class AtomIoClient
199205
url: "#{@baseURL}packages/search"
200206
headers: {'User-Agent': navigator.userAgent}
201207
qs: qs
202-
json: true
203208
gzip: true
204209
}
205210

@@ -210,9 +215,17 @@ class AtomIoClient
210215
error.stderr = err.message
211216
reject error
212217
else
213-
resolve(
214-
body.filter (pkg) -> pkg.releases?.latest?
215-
.map ({readme, metadata, downloads, stargazers_count}) ->
216-
Object.assign metadata, {readme, downloads, stargazers_count}
217-
.sort (a, b) -> b.downloads - a.downloads
218-
)
218+
try
219+
# NOTE: request's json option does not populate err if parsing fails,
220+
# so we do it manually
221+
body = JSON.parse(body)
222+
resolve(
223+
body.filter (pkg) -> pkg.releases?.latest?
224+
.map ({readme, metadata, downloads, stargazers_count}) ->
225+
Object.assign metadata, {readme, downloads, stargazers_count}
226+
.sort (a, b) -> b.downloads - a.downloads
227+
)
228+
catch e
229+
error = new Error("Searching for \u201C#{query}\u201D failed.")
230+
error.stderr = e.message + '\n' + body
231+
reject error

spec/atom-io-client-spec.coffee

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,29 @@ describe "AtomIoClient", ->
1111
expect(@client.fetchAndCacheAvatar).not.toHaveBeenCalled()
1212
@client.avatar 'test-user', ->
1313

14-
it "fetches api json from cache if the network is unavailable", ->
15-
spyOn(@client, 'online').andReturn(false)
16-
spyOn(@client, 'fetchFromCache').andCallFake (path, opts, cb) ->
17-
cb(null, {})
18-
spyOn(@client, 'request')
19-
@client.package 'test-package', ->
20-
21-
expect(@client.fetchFromCache).toHaveBeenCalled()
22-
expect(@client.request).not.toHaveBeenCalled()
14+
describe "request", ->
15+
it "fetches api json from cache if the network is unavailable", ->
16+
spyOn(@client, 'online').andReturn(false)
17+
spyOn(@client, 'fetchFromCache').andCallFake (path, opts, cb) ->
18+
cb(null, {})
19+
spyOn(@client, 'request')
20+
@client.package 'test-package', ->
21+
22+
expect(@client.fetchFromCache).toHaveBeenCalled()
23+
expect(@client.request).not.toHaveBeenCalled()
24+
25+
it "returns an error if the API response is not JSON", ->
26+
jsonParse = JSON.parse
27+
28+
waitsFor (done) ->
29+
spyOn(JSON, 'parse').andThrow()
30+
@client.request 'path', (error, data) ->
31+
expect(error).not.toBeNull()
32+
done()
33+
34+
runs ->
35+
# Tests will throw without this as cleanup requires JSON.parse to work
36+
JSON.parse = jsonParse
2337

2438
it "handles glob errors", ->
2539
spyOn(@client, 'avatarGlob').andReturn "#{__dirname}/**"

0 commit comments

Comments
 (0)