Browse Source

feat: add api server (#74)

Mainly two purposes:

1. Provide https://api.badgen.net
2. Serve this api behind Now CDN as a cache layer
badgesize
Amio / 6 years ago
committed by GitHub
parent
commit
fdb7ab493b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      libs/index-api.md
  2. 22
      libs/live-fetcher.js
  3. 27
      libs/live-handlers.js
  4. 26
      libs/serve-api.js
  5. 4
      now.json
  6. 4
      package.json
  7. 17
      service.js

6
libs/index-api.md

@ -0,0 +1,6 @@
# api.badgen.net
## Examples
- https://api.badgen.net/npm/v/micro
- https://api.badgen.net/npm/dependents/got

22
libs/live-badge-handlers.js → libs/live-fetcher.js

@ -1,26 +1,6 @@
const { get } = require('micro-fork')
const liveFns = require('./live-fns/_index.js')
const serveBadge = require('./serve-badge.js')
const waitings = {} // Cache ongoing fetching, prevent redundant request const waitings = {} // Cache ongoing fetching, prevent redundant request
module.exports = Object.entries(liveFns).map(([name, fn]) => { module.exports = async function fetchLiveParams (scope, fn, paramsPath) {
return get(`/${name}/*`, async (req, res) => {
const style = req.headers.host === 'flat.badgen.net' ? 'flat' : undefined
const {
subject = name,
status = 'unknown',
color = 'grey',
failed = false
} = await fetchLiveParams(name, fn, req.params['*'])
req.params = { subject, status, color, style }
serveBadge(req, res, {
maxAge: failed ? '0' : (Math.random() * 60 + 60).toFixed()
})
})
})
async function fetchLiveParams (scope, fn, paramsPath) {
const fetchKey = `#${scope} ${paramsPath}` const fetchKey = `#${scope} ${paramsPath}`
if (waitings[fetchKey]) return waitings[fetchKey] if (waitings[fetchKey]) return waitings[fetchKey]

27
libs/live-handlers.js

@ -0,0 +1,27 @@
const axios = require('./axios.js')
const { get } = require('micro-fork')
const liveFns = require('./live-fns/_index.js')
const serveBadge = require('./serve-badge.js')
const liveFetcher = require('./live-fetcher.js')
const { API_HOST } = process.env
module.exports = Object.entries(liveFns).map(([name, fn]) => {
return get(`/${name}/*`, async (req, res) => {
const {
subject = name,
status = 'unknown',
color = 'grey',
failed = false
} = await (API_HOST
? axios(API_HOST + req.url).then(res => res.data)
: liveFetcher(name, fn, req.params['*'])
)
const style = req.headers.host === 'flat.badgen.net' ? 'flat' : undefined
req.params = { subject, status, color, style }
serveBadge(req, res, {
maxAge: failed ? '0' : (Math.random() * 60 + 60).toFixed()
})
})
})

26
libs/serve-api.js

@ -0,0 +1,26 @@
const fs = require('fs')
const path = require('path')
const { send } = require('micro')
const { router, get } = require('micro-fork')
const liveFunctions = require('./live-fns/_index.js')
const liveFetcher = require('./live-fetcher.js')
const CACHE_CONTROL = `public, max-age=60, stale-while-revalidate=86400, stale-if-error=86400`
const sMaxAges = {
'github': '240'
}
const apiHandlers = Object.entries(liveFunctions).map(([name, fn]) => {
return get(`/${name}/*`, async (req, res) => {
res.setHeader('Cache-Control', `${CACHE_CONTROL}, s-maxage=${sMaxAges[name] || '120'}`)
send(res, 200, await liveFetcher(name, fn, req.params['*']))
})
})
const indexContent = fs.readFileSync(path.join(__dirname, 'index-api.md'), 'utf8')
const serveIndex = (req, res) => send(res, 200, indexContent)
module.exports = router()(
get('/', serveIndex),
...apiHandlers
)

4
now.json

@ -2,9 +2,9 @@
"alias": [ "alias": [
"badgen", "badgen",
"badgen.net", "badgen.net",
"flat.badgen.net" "flat.badgen.net",
"api.badgen.net"
], ],
"public": true,
"files": [ "files": [
"package-lock.json", "package-lock.json",
"service.js", "service.js",

4
package.json

@ -9,11 +9,11 @@
"dev": "micro-dev service.js -s", "dev": "micro-dev service.js -s",
"pretest": "npm run lint", "pretest": "npm run lint",
"test": "tap test/*.js --reporter spec -j12", "test": "tap test/*.js --reporter spec -j12",
"start": "micro service.js", "start": "node service.js",
"precanary": "now alias rm badgen-canary -y -T amio", "precanary": "now alias rm badgen-canary -y -T amio",
"canary": "now -T amio && now alias badgen-canary -T amio", "canary": "now -T amio && now alias badgen-canary -T amio",
"predeploy": "now rm badgen-service --safe -y -T amio || true", "predeploy": "now rm badgen-service --safe -y -T amio || true",
"deploy": "now -T amio && now alias -T amio" "deploy": "now -T amio -e API_HOST='https://api.badgen.net'"
}, },
"dependencies": { "dependencies": {
"axios": "^0.18.0", "axios": "^0.18.0",

17
service.js

@ -5,9 +5,10 @@ const serveIndex = require('./libs/serve-index.js')
const serve404 = require('./libs/serve-404.js') const serve404 = require('./libs/serve-404.js')
const serveDocs = require('./libs/serve-docs.js') const serveDocs = require('./libs/serve-docs.js')
const serveBadge = require('./libs/serve-badge.js') const serveBadge = require('./libs/serve-badge.js')
const liveBadgeHandlers = require('./libs/live-badge-handlers.js') const liveHandlers = require('./libs/live-handlers.js')
const serveApi = require('./libs/serve-api.js')
module.exports = router()( const main = router()(
get('/*', serve404), get('/*', serve404),
get('/', serveIndex), get('/', serveIndex),
get('/docs/:topic', serveDocs), get('/docs/:topic', serveDocs),
@ -15,9 +16,19 @@ module.exports = router()(
get('/favicon.svg', serveFavicon), get('/favicon.svg', serveFavicon),
get('/badge/:subject/:status', (req, res) => serveBadge(req, res)), get('/badge/:subject/:status', (req, res) => serveBadge(req, res)),
get('/badge/:subject/:status/:color', (req, res) => serveBadge(req, res)), get('/badge/:subject/:status/:color', (req, res) => serveBadge(req, res)),
...liveBadgeHandlers ...liveHandlers
) )
module.exports = function (req, res) {
switch (req.headers.host) {
case 'api.badgen.net':
case '127.0.0.1:3000':
return serveApi(req, res)
default:
return main(req, res)
}
}
if (require.main === module) { if (require.main === module) {
micro(module.exports).listen(3000) micro(module.exports).listen(3000)
} }

Loading…
Cancel
Save