Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update NJA to v1.0.2, change error response type to include level detail #130

Merged
merged 1 commit into from
Apr 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/lib/dynamodb_logs.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DB } from "./dynamodb"
import { ulid } from "ulid"

export const createLog = async (identifier: string, metadata: { [key: string]: string }, now: Date = new Date()): Promise<void> => {
export const createLog = async (identifier: string, metadata: { [key: string]: any }, now: Date = new Date()): Promise<void> => {
const nowStr = now.toISOString()
const datePart = nowStr.slice(0, 10)
const PK = `LOG#${identifier}#${datePart}`
Expand Down
4 changes: 2 additions & 2 deletions src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ export const yokobo2zenchoonSymbol = (str: string) => {
return str.replace(/[--﹣−‐⁃‑‒–—﹘―⎯⏤ーー─━]/gi,'ー') // 長音記号に変換
}

export const normalizeBuilding = (building: string | undefined ): string | undefined => {
if(undefined === building) {
export const normalizeBuilding = (building?: string ): string | undefined => {
if (typeof building === 'undefined' || building.trim() === "") {
return undefined
}
return yokobo2zenchoonSymbol(zen2hanAscii(building.trim()))
Expand Down
57 changes: 33 additions & 24 deletions src/public.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -268,35 +268,44 @@ test('should get estate ID with details if authenticated with 和歌山県東牟
])
})

test('should return 400 with insufficient address.', async () => {
const addresses = [
'和歌山県東牟婁郡'
]
describe("normalization error cases", () => {
test('should return 400 with insufficient address.', async () => {
const addresses = [
['和歌山県東牟婁郡', 'city_not_recognized'],
['和歌山県aoeu', 'city_not_recognized'],
['和歌県', 'prefecture_not_recognized'],
['おはよう', 'prefecture_not_recognized'],
]

for (const addressData of addresses) {
const [ address, expectedErrorCodeDetail ] = addressData
const event = {
isDemoMode: true,
queryStringParameters: {
q: address
}
}

// @ts-ignore
const resp = await handler(event) as APIGatewayProxyResult
const body = JSON.parse(resp.body)
expect(resp.statusCode).toEqual(400)
expect(body.error_code).toBe("normalization_failed")
expect(body.error_code_detail).toBe(expectedErrorCodeDetail)
}
})

for (const address of addresses) {
test('should return 400 with empty address', async () => {
const event = {
isDemoMode: true,
queryStringParameters: {
q: address
}
queryStringParameters: null
}

// @ts-ignore
const lambdaResult = await handler(event) as APIGatewayProxyResult
expect(lambdaResult.statusCode).toEqual(400)
}
})

test('should return 400 with empty address', async () => {
const event = {
isDemoMode: true,
queryStringParameters: null
}
// @ts-ignore
const { statusCode, body } = await handler(event)
const { message } = JSON.parse(body)
expect(statusCode).toEqual(400)
expect(message).toEqual('Missing querystring parameter `q`.')
const { statusCode, body } = await handler(event)
const { message } = JSON.parse(body)
expect(statusCode).toEqual(400)
expect(message).toEqual('Missing querystring parameter `q`.')
})
})

test('should return 403 if not authenticated.', async () => {
Expand Down
49 changes: 28 additions & 21 deletions src/public.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ import { Handler, APIGatewayProxyResult } from 'aws-lambda'
import { authenticateEvent, extractApiKey } from './lib/authentication'
import { createLog } from './lib/dynamodb_logs'

const NORMALIZATION_ERROR_CODE_DETAILS = [
"prefecture_not_recognized",
"city_not_recognized",
]

export const _handler: Handler<PublicHandlerEvent, APIGatewayProxyResult> = async (event) => {
const address = event.queryStringParameters?.q
const building = event.queryStringParameters?.building
Expand All @@ -33,27 +38,23 @@ export const _handler: Handler<PublicHandlerEvent, APIGatewayProxyResult> = asyn
})

// Internal normalization
let prenormalizedAddress: NormalizeResult
try {
prenormalizedAddress = await normalize(address)

await createLog(`normLogsNJA`, {
input: address,
normalized: JSON.stringify(prenormalizedAddress),
})
const prenormalizedAddress = await normalize(address)
await createLog(`normLogsNJA`, {
input: address,
level: prenormalizedAddress.level,
normalized: JSON.stringify(prenormalizedAddress),
})

} catch (error) {
Sentry.captureException(error)
console.error({ error })
if ('address' in error) {
// this is a normalize-japanese-addressses error
await createLog(`normFailNJA`, {
input: address,
errorMsg: error.message,
})
}
return errorResponse(400, `address ${address} can not be normalized.`)
if (prenormalizedAddress.level < 2) {
const error_code_detail = NORMALIZATION_ERROR_CODE_DETAILS[prenormalizedAddress.level]
return json({
error: true,
error_code: `normalization_failed`,
error_code_detail,
address,
}, 400)
}

const normalizedBuilding = normalizeBuilding(building)

if (!prenormalizedAddress.town || prenormalizedAddress.town === '') {
Expand All @@ -65,6 +66,7 @@ export const _handler: Handler<PublicHandlerEvent, APIGatewayProxyResult> = asyn
const normalizedAddressNJA = `${prenormalizedAddress.pref}${prenormalizedAddress.city}${prenormalizedAddress.town}${prenormalizedAddress.addr}`
const ipcResult = await incrementPGeocode(normalizedAddressNJA)
if (!ipcResult) {
Sentry.captureException(new Error(`IPC result null`))
return errorResponse(500, 'Internal server error')
}

Expand All @@ -81,7 +83,12 @@ export const _handler: Handler<PublicHandlerEvent, APIGatewayProxyResult> = asyn
prenormalized: normalizedAddressNJA,
ipcResult: JSON.stringify(ipcResult),
})
return errorResponse(404, "The address '%s' is not verified.", address)

return json({
error: true,
error_code: `address_not_verified`,
address,
}, 404)
}

const [lng, lat] = feature.geometry.coordinates as [number, number]
Expand Down Expand Up @@ -137,7 +144,7 @@ export const _handler: Handler<PublicHandlerEvent, APIGatewayProxyResult> = asyn
return errorResponse(500, 'Internal Server Error.')
}

const ID = estateId!.estateId
const ID = estateId.estateId

let body: any
if (authenticationResult.plan === "paid" || event.isDemoMode) {
Expand Down
6 changes: 3 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -310,9 +310,9 @@
integrity sha512-LO1f4Bw/UF5OIWAavX9CyclxYCsHPDe6h/CWL/1RInc3QLMkEGicZp++qyfjodDsPKMCs84GReJapQnPWl3ZUQ==

"@geolonia/normalize-japanese-addresses@*":
version "0.1.9"
resolved "https://registry.yarnpkg.com/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-0.1.9.tgz#59aa9597dafcb4170c31b947bfac7833b1f8e24f"
integrity sha512-/D+D5GjrjmR34N1S5p/sbRsortR0fGYncdWLJMUADvEZUzo4mP6fSwbfEDXS7Rz9W9+bFbRpKC1piRBY+iehwg==
version "1.0.2"
resolved "https://registry.yarnpkg.com/@geolonia/normalize-japanese-addresses/-/normalize-japanese-addresses-1.0.2.tgz#e1bab3443265b1288e9798aa6e9de1509222431b"
integrity sha512-KfewiWewUhrAkzrvQeqFH+AXonCqDRjGlR18qiXmA78gtq0GzyeXIZHCowMY3iwd1wRaEZ6PgZXA+FLNvUCCJQ==
dependencies:
"@geolonia/japanese-numeral" "^0.1.11"
node-fetch "^2.6.1"
Expand Down