1
+ // For AutoRouter documentation refer to https://itty.dev/itty-router/routers/autorouter
2
+ import { AutoRouter } from 'itty-router' ;
3
+ import { getClientAddressFromRequest , cleanupIpAddress } from "./helpers" ;
4
+ import { Variables } from "@fermyon/spin-sdk" ;
5
+
6
+
7
+ let router = AutoRouter ( ) ;
8
+
9
+ // Route ordering matters, the first route that matches will be used
10
+ // Any route that does not return will be treated as a middleware
11
+ // Any unmatched route will return a 404
12
+ router
13
+ . get ( "/" , getWeather ) ;
14
+
15
+ //@ts -ignore
16
+ addEventListener ( 'fetch' , async ( event : FetchEvent ) => {
17
+ event . respondWith ( router . fetch ( event . request ) ) ;
18
+ } ) ;
19
+
20
+ async function getWeather ( request : Request ) : Promise < Response > {
21
+ console . log ( "Request received" , request . headers . get ( "spin-client-addr" ) ) ;
22
+
23
+ const clientAddress = getClientAddressFromRequest ( request ) ;
24
+ if ( ! clientAddress ) {
25
+ return new Response ( "Could not determine client ip address" , { status : 500 } ) ;
26
+ }
27
+
28
+ let ip = cleanupIpAddress ( clientAddress ) ;
29
+ console . log ( `Client IP: ${ ip } ` ) ;
30
+ ip = ip === "127.0.0.1" ? Variables . get ( "test_ip_addr" ) ?? ip : ip ;
31
+
32
+ let longitude , latitude ;
33
+ try {
34
+ [ latitude , longitude ] = await getGeolocation ( ip ) ;
35
+ } catch ( error ) {
36
+ if ( ip == "127.0.0.1" ) {
37
+ return new Response ( "Unable to get geolocation data for localhost, try using test_ip_addr variable" , { status : 500 } ) ;
38
+ }
39
+ return new Response ( "Failed to get geolocation data" , { status : 500 } ) ;
40
+ }
41
+
42
+
43
+ let endpoint = "https://api.waqi.info/feed/geo:" ;
44
+ let token = Variables . get ( "waqi_api_token" ) ; //Use a token from https://aqicn.org/api/
45
+ let html_style = `body{padding:6em; font-family: sans-serif;} h1{color:#f6821f}` ;
46
+
47
+ let html_content = "<h1>Weather 🌦</h1>" ;
48
+
49
+ endpoint += `${ latitude } ;${ longitude } /?token=${ token } ` ;
50
+ const init = {
51
+ headers : {
52
+ "content-type" : "application/json;charset=UTF-8" ,
53
+ } ,
54
+ } ;
55
+
56
+ const response = await fetch ( endpoint , init ) ;
57
+ console . log ( "response" , response . status ) ;
58
+ if ( response . status !== 200 ) {
59
+ return new Response ( "Failed to get weather info" , { status : 500 } ) ;
60
+ }
61
+ const content = await response . json ( ) ;
62
+
63
+ html_content += `<p>This is a demo using geolocation data. </p>` ;
64
+ html_content += `You are located at: ${ latitude } ,${ longitude } .</p>` ;
65
+ html_content += `<p>Based off sensor data from <a href="${ content . data . city . url } ">${ content . data . city . name } </a>:</p>` ;
66
+ html_content += `<p>The temperature is: ${ content . data . iaqi . t ?. v } °C.</p>` ;
67
+ html_content += `<p>The AQI level is: ${ content . data . aqi } .</p>` ;
68
+ html_content += `<p>The N02 level is: ${ content . data . iaqi . no2 ?. v } .</p>` ;
69
+ html_content += `<p>The O3 level is: ${ content . data . iaqi . o3 ?. v } .</p>` ;
70
+
71
+ let html = `
72
+ <!DOCTYPE html>
73
+ <head>
74
+ <title>Geolocation: Weather</title>
75
+ </head>
76
+ <body>
77
+ <style>${ html_style } </style>
78
+ <div id="container">
79
+ ${ html_content }
80
+ </div>
81
+ </body>` ;
82
+
83
+ return new Response ( html , {
84
+ headers : {
85
+ "content-type" : "text/html;charset=UTF-8" ,
86
+ } ,
87
+ } ) ;
88
+ }
89
+
90
+ async function getGeolocation ( ip : string ) : Promise < [ number , number ] > {
91
+ console . log ( "Fetching geolocation data for" , ip ) ;
92
+ const response = await fetch ( `https://ip-api.io/json/${ ip } ` ) ;
93
+ if ( ! response . ok ) {
94
+ throw new Error ( `Failed to fetch geolocation data: ${ response . status } ` ) ;
95
+ }
96
+ const data = await response . json ( ) ;
97
+ return [ data . latitude , data . longitude ] ;
98
+ }
0 commit comments