New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

featureservice

Package Overview
Dependencies
Maintainers
2
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

featureservice - npm Package Compare versions

Comparing version 1.5.0 to 1.5.1

6

CHANGELOG.md

@@ -5,2 +5,7 @@ # Change Log

## [1.5.1] - 2016-03-02
### Changed
* Don't use resultOffset for services not hosted on ArcGIS Online, it's not reliable
* Decode streaming server response
## [1.5.0] - 2016-02-28

@@ -184,2 +189,3 @@ ### Added

[1.5.1]: https://github.com/koopjs/featureservice/compare/v1.5.0...v1.5.1
[1.5.0]: https://github.com/koopjs/featureservice/compare/v1.4.6...v1.5.0

@@ -186,0 +192,0 @@ [1.4.6]: https://github.com/koopjs/featureservice/compare/v1.4.5...v1.4.6

80

index.js

@@ -5,2 +5,3 @@ var queue = require('async').queue

var zlib = require('zlib')
var stream = require('stream')
var urlUtils = require('url')

@@ -24,2 +25,3 @@ var Utils = require('./lib/utils.js')

var service = Utils.parseUrl(url)
this.hosted = service.hosted
this.server = service.server

@@ -96,14 +98,11 @@ this.options = options || {}

var req = ((uri.protocol === 'https:') ? https : http).request(opts, function (response) {
var encoding = response.headers['content-encoding']
var data = []
response.on('data', function (chunk) {
data.push(chunk)
})
response.on('error', function (err) {
callback(err)
})
response.on('end', function () {
self._decode(response, data, callback)
})
response
// TODO standaridize these errors
.on('error', function (err) { return callback(err) })
.pipe(decode(encoding))
.on('error', function (err) { return callback(err) })
.on('data', function (chunk) { data.push(chunk) })
.on('end', function () { parse(data, callback) })
})

@@ -337,3 +336,3 @@

if (err) return callback(err)
this.concurrency = this.options.concurrency || Utils.setConcurrency(this.server, meta.layer.geometryType)
this.concurrency = this.options.concurrency || Utils.setConcurrency(this.hosted, meta.layer.geometryType)
this.maxConcurrency = this.concurrency

@@ -350,3 +349,3 @@ this.pageQueue.concurrency = this.concurrency

var canPage = layer.advancedQueryCapabilities && layer.advancedQueryCapabilities.supportsPagination
if (canPage) return callback(null, this._offsetPages(nPages, size))
if (canPage && !this.hosted) return callback(null, this._offsetPages(nPages, size))

@@ -509,17 +508,15 @@ if (!meta.oid) return callback(new Error('ObjectID type field not found, unable to page'))

var req = ((url_parts.protocol === 'https:') ? https : http).request(opts, function (response) {
var data = []
response.on('data', function (chunk) {
data.push(chunk)
var encoding = response.headers['content-encoding']
var buffer = []
response
.on('error', function (err) { self._catchErrors(task, err, uri, cb) })
.pipe(decode(encoding))
.on('error', function (error) {
return self._catchErrors(task, error, uri, cb)
})
response.on('error', function (err) {
self._catchErrors(task, err, uri, cb)
})
response.on('end', function () {
self._decode(response, data, function (err, json) {
// the error coming back here is already well formed in _decode
.on('data', function (chunk) { buffer.push(chunk) })
.on('end', function () {
// server responds 200 with error in the payload so we have to inspect
parse(buffer, function (err, json) {
if (err) return self._catchErrors(task, err, uri, cb)
// server responds 200 with error in the payload so we have to inspect
if (!json || json.error) {

@@ -534,3 +531,3 @@ if (!json) json = {error: {}}

self._throttleQueue()
cb(null, json, task)
cb(null, json)
})

@@ -564,24 +561,6 @@ })

/* Decodes a response for features
* @param {object} res - the response received from the GIS Server
* @param {array} data - an array of chunks received from the server
* @param {function} callback - calls back with either an error or the decoded feature json
*/
FeatureService.prototype._decode = function (res, data, callback) {
var encoding = res.headers['content-encoding']
if (!data.length > 0) return callback(new Error('Response from the server was empty'))
var buffer = Buffer.concat(data)
if (encoding === 'gzip') {
zlib.gunzip(buffer, function (err, decompressed) {
if (err) return callback(err)
parse(decompressed, callback)
})
} else if (encoding === 'deflate') {
zlib.inflate(buffer, function (err, decompressed) {
if (err) return callback(err)
parse(decompressed, callback)
})
} else {
parse(buffer, callback)
}
function decode (encoding) {
if (encoding === 'gzip') return zlib.createGunzip()
else if (encoding === 'deflate') return zlib.createInflate()
else return stream.PassThrough()
}

@@ -593,5 +572,6 @@

try {
response = buffer.toString()
response = Buffer.concat(buffer).toString()
parsed = JSON.parse(response)
} catch (e) {
console.log(e)
// sometimes we get html or plain strings back

@@ -598,0 +578,0 @@ var pattern = new RegExp(/[^{\[]/)

@@ -5,9 +5,8 @@ module.exports = {

*
* @param {string} service - the feature or map service targeted
* @param {boolean} hosted - whether or not the service is hosted on ArcGIS Online
* @param {string} geomType - the geometry type of the features in the service
* @return {integer} the suggested concurrency
*/
setConcurrency: function (service, geomType) {
var isHosted = service.match(/services(\d)?(qa|dev)?.arcgis.com/)
var naieve = isHosted ? 16 : 4
setConcurrency: function (hosted, geomType) {
var naieve = hosted ? 16 : 4
if (!geomType) return naieve

@@ -17,2 +16,7 @@ var concurrency = geomType.match(/point/i) ? naieve : naieve / 4

},
/**
* Parsed the layer and server from a feature service url
* @param {string} url - a link to a feature service
* @return {object} contains the layer, the server and whether or not the server is hosted
*/
parseUrl: function (url) {

@@ -22,5 +26,6 @@ var layer = url.match(/(?:.+\/(?:feature|map)server\/)(\d+)/i)

layer: layer && layer[1] ? layer[1] : undefined,
server: url.match(/.+\/(feature|map)server/i)[0]
server: url.match(/.+\/(feature|map)server/i)[0],
hosted: /services(\d)?(qa|dev)?.arcgis.com/.test(url)
}
}
}
{
"name": "featureservice",
"description": "Get all features from an Esri Feature Service",
"version": "1.5.0",
"version": "1.5.1",
"author": "Chris Helm",

@@ -6,0 +6,0 @@ "bugs": {

@@ -7,4 +7,4 @@ var sinon = require('sinon')

var fs = require('fs')
var _ = require('lodash')
var zlib = require('zlib')
var _ = require('lodash')

@@ -283,76 +283,2 @@ var service = new FeatureService('http://koop.dc.esri.com/socrata/seattle/2tje-83f6/FeatureServer/1', {objectIdField: 'OBJECTID'})

test('decoding something that is gzipped', function (t) {
var json = JSON.stringify(JSON.parse(fs.readFileSync('./test/fixtures/uncompressed.json')))
zlib.gzip(json, function (err, gzipped) {
t.error(err)
var data = [gzipped]
var res = {headers: {'content-encoding': 'gzip'}}
var service = new FeatureService('http://service.com/mapserver/2')
service._decode(res, data, function (error, json) {
t.equal(error, null)
t.equal(json.features.length, 2000)
t.end()
})
})
})
test('decoding something that is deflated', function (t) {
var json = JSON.stringify(JSON.parse((fs.readFileSync('./test/fixtures/uncompressed.json'))))
zlib.deflate(json, function (err, deflated) {
t.error(err)
var data = [deflated]
var res = {headers: {'content-encoding': 'deflate'}}
service._decode(res, data, function (error, json) {
t.equal(error, null)
t.equal(json.features.length, 2000)
t.end()
})
})
})
test('decoding something that is not compressed', function (t) {
var uncompressed = JSON.stringify(JSON.parse(fs.readFileSync('./test/fixtures/uncompressed.json')))
var buffer = new Buffer(uncompressed)
var buf1 = buffer.slice(0, -1)
var buf2 = buffer.slice(-1)
var data = [buf1, buf2]
var res = {headers: {}}
service._decode(res, data, function (err, json) {
t.error(err)
t.equal(json.features.length, 2000)
t.end()
})
})
test('decoding an empty response', function (t) {
var empty = []
var res = {headers: {'content-encoding': 'gzip'}}
service._decode(res, empty, function (err, json) {
t.notEqual(typeof err, 'undefined')
t.end()
})
})
test('decoding an unexpected HMTL response', function (t) {
var res = {headers: {'content-encoding': ''}}
var data = [new Buffer('</html></html>')]
service._decode(res, data, function (err) {
t.equal(err.message, 'Received HTML or plain text when expecting JSON')
t.end()
})
})
test('decoding an unexpected plain text response', function (t) {
var res = {headers: {'content-encoding': ''}}
var data = [new Buffer('Bad request')]
service._decode(res, data, function (err) {
t.equal(err.message, 'Received HTML or plain text when expecting JSON')
t.end()
})
})
test('should trigger catchErrors with an error when receiving json with an error in the response', function (t) {

@@ -387,7 +313,7 @@ var data = {

test('requesting a page of features', function (t) {
var page = fs.readFileSync('./test/fixtures/page.json')
var page = fs.createReadStream('./test/fixtures/page.json')
var fixture = nock('http://servicesqa.arcgis.com')
fixture.get('/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision=')
.reply(200, page)
.reply(200, function () { return page })

@@ -404,2 +330,71 @@ var service = new FeatureService('http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0')

test('requesting a page of features that is gzipped', function (t) {
var page = fs.createReadStream('./test/fixtures/page.json').pipe(zlib.createGzip())
var fixture = nock('http://servicesqa.arcgis.com')
fixture.get('/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision=')
.reply(200, function () { return page }, {'content-encoding': 'gzip'})
var service = new FeatureService('http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0')
var task = {req: 'http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision='}
service._requestFeatures(task, function (err, json) {
t.error(err)
t.equal(json.features.length, 1000)
t.end()
})
})
test('requesting a page of features that is deflate encoded', function (t) {
var page = fs.createReadStream('./test/fixtures/page.json').pipe(zlib.createDeflate())
var fixture = nock('http://servicesqa.arcgis.com')
fixture.get('/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision=')
.reply(200, function () { return page }, {'content-encoding': 'deflate'})
var service = new FeatureService('http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0')
var task = {req: 'http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision='}
service._requestFeatures(task, function (err, json) {
t.error(err)
t.equal(json.features.length, 1000)
t.end()
})
})
test('requesting a page of features and getting an html response', function (t) {
var page = new Buffer('</html></html>')
var fixture = nock('http://servicesqa.arcgis.com')
fixture.get('/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision=')
.times(4)
.reply(200, function () { return page })
var service = new FeatureService('http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0', {backoff: 1})
var task = {req: 'http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision='}
service._requestFeatures(task, function (err, json) {
t.ok(err)
t.equal(err.message, 'Paging aborted: Received HTML or plain text when expecting JSON')
t.end()
})
})
test('requesting a page of features and getting an empty response', function (t) {
var fixture = nock('http://servicesqa.arcgis.com')
fixture.get('/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision=')
.times(4)
.reply(200, function () { return undefined })
var service = new FeatureService('http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0', {backoff: 1})
var task = {req: 'http://servicesqa.arcgis.com/97KLIFOSt5CxbiRI/arcgis/rest/services/QA_data_simple_point_5000/FeatureServer/0/query?outSR=4326&f=json&outFields=*&where=1=1&resultOffset=1000&resultRecordCount=1000&geometry=&returnGeometry=true&geometryPrecision='}
service._requestFeatures(task, function (err, json) {
t.ok(err)
t.equal(err.message, 'Paging aborted: Failed to parse server response')
t.end()
})
})
// paging integration tests

@@ -561,3 +556,3 @@ test('building pages for a service that supports pagination', function (t) {

t.plan(1)
var concurrency = Utils.setConcurrency('http://services.arcgis.com/mapserver/3', 'esriGeometryPolygon')
var concurrency = Utils.setConcurrency(true, 'esriGeometryPolygon')
t.equal(concurrency, 4)

@@ -568,3 +563,3 @@ })

t.plan(1)
var concurrency = Utils.setConcurrency('http://foo.com/mapserver/2', 'esriGeometryLine')
var concurrency = Utils.setConcurrency(false, 'esriGeometryLine')
t.equal(concurrency, 1)

@@ -575,3 +570,3 @@ })

t.plan(1)
var concurrency = Utils.setConcurrency('http://services.arcgis.com/featureserver/3', 'esriGeometryPoint')
var concurrency = Utils.setConcurrency(true, 'esriGeometryPoint')
t.equal(concurrency, 16)

@@ -582,4 +577,4 @@ })

t.plan(1)
var concurrency = Utils.setConcurrency('http://foo.com/featureserver/3', 'esriGeometryPoint')
var concurrency = Utils.setConcurrency(false, 'esriGeometryPoint')
t.equal(concurrency, 4)
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc