I'm currently playing with the google places api to gain some comfort level with it, but I've come up on an issue that has me a little stumped and I'm hoping someone can course correct me here. I'm making api calls to a local proxy server, and so far everything is working except when I try to pull an image for a specific business.
I've gone so far as to console log each individual part of the get request url to ensure it's correctly concatenated and everything appears correct in that regard (I'm able to paste it straight into the browser and get the expected result). I have a hunch this is a general code issue and not something specific to places api itself, but any insight into this would be greatly appreciated.
Error in terminal from proxy server (doesn't seem terribly useful, but someone else might recognize something here that I'm not):
undefined:1 ���� ^
SyntaxError: Unexpected token � in JSON at position 0
Front end code:
function makeAPICall(url) {
return fetch(url);
}
makeAPICall(`http://localhost:5000/places/${searchString}`)
.then(response => {
return response.json();
})
.then(data => {
responseObject = data.results;
renderResult(responseObject[10]);
return responseObject[10];
})
.then(responseObject => {
makeAPICall(`http://localhost:5000/place/image/${responseObject.photos[0].photo_reference}`)
.then(response => {
return response.json();
})
.then(photoData => {
console.log(photoData);
});
});
Proxy code (minus the working routes not relevant to the issue):
require('dotenv').config({path: '../.env'});
const express = require('express');
const request = require('request');
const GOOGLE_API_KEY = process.env.API_KEY;
const placesImgURL = 'https://maps.googleapis.com/maps/api/place/photo?maxwidth=400&photoreference=';
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
next();
});
app.get('/place/image/:query', (req, res) => {
request(
{ url: `${placesImgURL}${req.params.query}&key=${GOOGLE_API_KEY}` },
(error, response, body) => {
if (error || response.statusCode !== 200) {
console.log(response);
}
res.json(JSON.parse(body));
}
)
});
const PORT = process.env.PORT || 4000;
app.listen(PORT, () => console.log(`listening on ${PORT}`));
UPDATE:
The line in the server code where the error is triggered is:
res.json(JSON.parse(body));
Screenshot of network call from within dev tools:
When console logging the line that's throwing an error, I get the following (fair warning, this is the full log and it's extremely long):
ServerResponse {
_events: { finish: [Function: bound resOnFinish] },
_eventsCount: 1,
_maxListeners: undefined,
output: [],
outputEncodings: [],
outputCallbacks: [],
outputSize: 0,
writable: true,
_last: false,
chunkedEncoding: false,
shouldKeepAlive: true,
useChunkedEncodingByDefault: true,
sendDate: true,
_removedConnection: false,
_removedContLen: false,
_removedTE: false,
_contentLength: 22631,
_hasBody: true,
_trailer: '',
finished: true,
_headerSent: true,
socket:
Socket {
connecting: false,
_hadError: false,
_handle:
TCP {
reading: true,
onread: [Function: onStreamRead],
onconnection: null,
_consumed: true,
[Symbol(owner)]: [Circular] },
_parent: null,
_host: null,
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: false,
endEmitted: false,
reading: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
emitClose: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
_events:
{ end: [Array],
drain: [Array],
timeout: [Function: socketOnTimeout],
data: [Function: bound socketOnData],
error: [Function: socketOnError],
close: [Array],
resume: [Function: onSocketResume],
pause: [Function: onSocketPause] },
_eventsCount: 8,
_maxListeners: undefined,
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: true,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 3,
prefinished: false,
errorEmitted: false,
emitClose: false,
bufferedRequestCount: 0,
corkedRequestsFree: [Object] },
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server:
Server {
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_connections: 1,
_handle: [TCP],
_usingWorkers: false,
_workers: [],
_unref: false,
allowHalfOpen: true,
pauseOnConnect: false,
httpAllowHalfOpen: false,
timeout: 120000,
keepAliveTimeout: 5000,
_pendingResponseData: 0,
maxHeadersCount: null,
_connectionKey: '6::::5000',
[Symbol(IncomingMessage)]: [Function],
[Symbol(ServerResponse)]: [Function],
[Symbol(asyncId)]: 5 },
_server:
Server {
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_connections: 1,
_handle: [TCP],
_usingWorkers: false,
_workers: [],
_unref: false,
allowHalfOpen: true,
pauseOnConnect: false,
httpAllowHalfOpen: false,
timeout: 120000,
keepAliveTimeout: 5000,
_pendingResponseData: 0,
maxHeadersCount: null,
_connectionKey: '6::::5000',
[Symbol(IncomingMessage)]: [Function],
[Symbol(ServerResponse)]: [Function],
[Symbol(asyncId)]: 5 },
timeout: 120000,
parser:
HTTPParser {
'0': [Function: parserOnHeaders],
'1': [Function: parserOnHeadersComplete],
'2': [Function: parserOnBody],
'3': [Function: parserOnMessageComplete],
'4': [Function: bound onParserExecute],
_headers: [],
_url: '',
_consumed: true,
socket: [Circular],
incoming: [IncomingMessage],
outgoing: null,
maxHeaderPairs: 2000,
onIncoming: [Function: bound parserOnIncoming] },
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 8,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]:
Timeout {
_called: false,
_idleTimeout: 120000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 6746,
_onTimeout: [Function: bound ],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(unrefed)]: true,
[Symbol(asyncId)]: 9,
[Symbol(triggerId)]: 8 },
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
connection:
Socket {
connecting: false,
_hadError: false,
_handle:
TCP {
reading: true,
onread: [Function: onStreamRead],
onconnection: null,
_consumed: true,
[Symbol(owner)]: [Circular] },
_parent: null,
_host: null,
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: true,
ended: false,
endEmitted: false,
reading: true,
sync: false,
needReadable: true,
emittedReadable: false,
readableListening: false,
resumeScheduled: false,
emitClose: false,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: false,
decoder: null,
encoding: null },
readable: true,
_events:
{ end: [Array],
drain: [Array],
timeout: [Function: socketOnTimeout],
data: [Function: bound socketOnData],
error: [Function: socketOnError],
close: [Array],
resume: [Function: onSocketResume],
pause: [Function: onSocketPause] },
_eventsCount: 8,
_maxListeners: undefined,
_writableState:
WritableState {
objectMode: false,
highWaterMark: 16384,
finalCalled: false,
needDrain: true,
ending: false,
ended: false,
finished: false,
destroyed: false,
decodeStrings: false,
defaultEncoding: 'utf8',
length: 0,
writing: false,
corked: 0,
sync: false,
bufferProcessing: false,
onwrite: [Function: bound onwrite],
writecb: null,
writelen: 0,
bufferedRequest: null,
lastBufferedRequest: null,
pendingcb: 3,
prefinished: false,
errorEmitted: false,
emitClose: false,
bufferedRequestCount: 0,
corkedRequestsFree: [Object] },
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server:
Server {
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_connections: 1,
_handle: [TCP],
_usingWorkers: false,
_workers: [],
_unref: false,
allowHalfOpen: true,
pauseOnConnect: false,
httpAllowHalfOpen: false,
timeout: 120000,
keepAliveTimeout: 5000,
_pendingResponseData: 0,
maxHeadersCount: null,
_connectionKey: '6::::5000',
[Symbol(IncomingMessage)]: [Function],
[Symbol(ServerResponse)]: [Function],
[Symbol(asyncId)]: 5 },
_server:
Server {
_events: [Object],
_eventsCount: 2,
_maxListeners: undefined,
_connections: 1,
_handle: [TCP],
_usingWorkers: false,
_workers: [],
_unref: false,
allowHalfOpen: true,
pauseOnConnect: false,
httpAllowHalfOpen: false,
timeout: 120000,
keepAliveTimeout: 5000,
_pendingResponseData: 0,
maxHeadersCount: null,
_connectionKey: '6::::5000',
[Symbol(IncomingMessage)]: [Function],
[Symbol(ServerResponse)]: [Function],
[Symbol(asyncId)]: 5 },
timeout: 120000,
parser:
HTTPParser {
'0': [Function: parserOnHeaders],
'1': [Function: parserOnHeadersComplete],
'2': [Function: parserOnBody],
'3': [Function: parserOnMessageComplete],
'4': [Function: bound onParserExecute],
_headers: [],
_url: '',
_consumed: true,
socket: [Circular],
incoming: [IncomingMessage],
outgoing: null,
maxHeaderPairs: 2000,
onIncoming: [Function: bound parserOnIncoming] },
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 8,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]:
Timeout {
_called: false,
_idleTimeout: 120000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 6746,
_onTimeout: [Function: bound ],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(unrefed)]: true,
[Symbol(asyncId)]: 9,
[Symbol(triggerId)]: 8 },
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
_header:
'HTTP/1.1 200 OK\r\nX-Powered-By: Express\r\nAccess-Control-Allow-Origin: *\r\nContent-Type: application/json; charset=utf-8\r\nContent-Length: 22631\r\nETag: W/"5867-c3Fodr1eSCA3vlKX+kDMgudDONQ"\r\nDate: Wed, 26 Aug 2020 18:14:27 GMT\r\nConnection: keep-alive\r\n\r\n',
_onPendingData: [Function: bound updateOutgoingData],
_sent100: false,
_expect_continue: false,
req:
IncomingMessage {
_readableState:
ReadableState {
objectMode: false,
highWaterMark: 16384,
buffer: BufferList { head: null, tail: null, length: 0 },
length: 0,
pipes: null,
pipesCount: 0,
flowing: null,
ended: true,
endEmitted: false,
reading: false,
sync: true,
needReadable: false,
emittedReadable: true,
readableListening: false,
resumeScheduled: false,
emitClose: true,
destroyed: false,
defaultEncoding: 'utf8',
awaitDrain: 0,
readingMore: true,
decoder: null,
encoding: null },
readable: true,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
socket:
Socket {
connecting: false,
_hadError: false,
_handle: [TCP],
_parent: null,
_host: null,
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
timeout: 120000,
parser: [HTTPParser],
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 8,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]:
Timeout {
_called: false,
_idleTimeout: 120000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 6746,
_onTimeout: [Function: bound ],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(unrefed)]: true,
[Symbol(asyncId)]: 9,
[Symbol(triggerId)]: 8 },
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
connection:
Socket {
connecting: false,
_hadError: false,
_handle: [TCP],
_parent: null,
_host: null,
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
timeout: 120000,
parser: [HTTPParser],
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 8,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]:
Timeout {
_called: false,
_idleTimeout: 120000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 6746,
_onTimeout: [Function: bound ],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(unrefed)]: true,
[Symbol(asyncId)]: 9,
[Symbol(triggerId)]: 8 },
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
httpVersionMajor: 1,
httpVersionMinor: 1,
httpVersion: '1.1',
complete: true,
headers:
{ host: 'localhost:5000',
connection: 'keep-alive',
'user-agent':
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36',
accept: '*/*',
origin: 'http://localhost:3000',
'sec-fetch-site': 'same-site',
'sec-fetch-mode': 'cors',
'sec-fetch-dest': 'empty',
referer: 'http://localhost:3000/',
'accept-encoding': 'gzip, deflate, br',
'accept-language': 'en-US,en;q=0.9',
'if-none-match': 'W/"5868-+iRV2Q1kdgam9TbgiDgKID9Vs1s"' },
rawHeaders:
[ 'Host',
'localhost:5000',
'Connection',
'keep-alive',
'User-Agent',
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.125 Safari/537.36',
'Accept',
'*/*',
'Origin',
'http://localhost:3000',
'Sec-Fetch-Site',
'same-site',
'Sec-Fetch-Mode',
'cors',
'Sec-Fetch-Dest',
'empty',
'Referer',
'http://localhost:3000/',
'Accept-Encoding',
'gzip, deflate, br',
'Accept-Language',
'en-US,en;q=0.9',
'If-None-Match',
'W/"5868-+iRV2Q1kdgam9TbgiDgKID9Vs1s"' ],
trailers: {},
rawTrailers: [],
aborted: false,
upgrade: false,
url: '/places/restaurants+near%20me',
method: 'GET',
statusCode: null,
statusMessage: null,
client:
Socket {
connecting: false,
_hadError: false,
_handle: [TCP],
_parent: null,
_host: null,
_readableState: [ReadableState],
readable: true,
_events: [Object],
_eventsCount: 8,
_maxListeners: undefined,
_writableState: [WritableState],
writable: true,
allowHalfOpen: true,
_sockname: null,
_pendingData: null,
_pendingEncoding: '',
server: [Server],
_server: [Server],
timeout: 120000,
parser: [HTTPParser],
on: [Function: socketOnWrap],
_paused: false,
_httpMessage: [Circular],
[Symbol(asyncId)]: 8,
[Symbol(lastWriteQueueSize)]: 0,
[Symbol(timeout)]:
Timeout {
_called: false,
_idleTimeout: 120000,
_idlePrev: [TimersList],
_idleNext: [TimersList],
_idleStart: 6746,
_onTimeout: [Function: bound ],
_timerArgs: undefined,
_repeat: null,
_destroyed: false,
[Symbol(unrefed)]: true,
[Symbol(asyncId)]: 9,
[Symbol(triggerId)]: 8 },
[Symbol(kBytesRead)]: 0,
[Symbol(kBytesWritten)]: 0 },
_consuming: false,
_dumped: false,
next: [Function: next],
baseUrl: '',
originalUrl: '/places/restaurants+near%20me',
_parsedUrl:
Url {
protocol: null,
slashes: null,
auth: null,
host: null,
port: null,
hostname: null,
hash: null,
search: null,
query: null,
pathname: '/places/restaurants+near%20me',
path: '/places/restaurants+near%20me',
href: '/places/restaurants+near%20me',
_raw: '/places/restaurants+near%20me' },
params: { query: 'restaurants+near me' },
query: {},
res: [Circular],
route:
Route { path: '/places/:query', stack: [Array], methods: [Object] } },
locals: {},
statusMessage: 'OK',
statusCode: 200,
[Symbol(isCorked)]: false,
[Symbol(outHeadersKey)]:
{ 'x-powered-by': [ 'X-Powered-By', 'Express' ],
'access-control-allow-origin': [ 'Access-Control-Allow-Origin', '*' ],
'content-type': [ 'Content-Type', 'application/json; charset=utf-8' ],
'content-length': [ 'Content-Length', '22631' ],
etag: [ 'ETag', 'W/"5867-c3Fodr1eSCA3vlKX+kDMgudDONQ"' ] } }
_http_outgoing.js:470
throw new ERR_HTTP_HEADERS_SENT('set');
^
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (/Users/tyleranyan/Documents/api-practice/places/node_modules/express/lib/response.js:771:10)
at ServerResponse.send (/Users/tyleranyan/Documents/api-practice/places/node_modules/express/lib/response.js:170:12)
at ServerResponse.json (/Users/tyleranyan/Documents/api-practice/places/node_modules/express/lib/response.js:267:15)
at Request.request [as _callback] (/Users/tyleranyan/Documents/api-practice/places/proxy/server.js:25:11)
at Request.self.callback (/Users/tyleranyan/Documents/api-practice/places/node_modules/request/request.js:185:22)
at Request.emit (events.js:182:13)
at Request.<anonymous> (/Users/tyleranyan/Documents/api-practice/places/node_modules/request/request.js:1154:10)
at Request.emit (events.js:182:13)
at IncomingMessage.<anonymous> (/Users/tyleranyan/Documents/api-practice/places/node_modules/request/request.js:1076:12)