Version 0.3.0

Squashed commit of the following:

commit 50f699bb966a014c92ecbb05f96a05fe515ff6d8
Author: Foster Hangdaan <foster@hangdaan.email>
Date:   Tue Nov 14 20:58:51 2023 -0500

    doc: Update README.org

    - Added a table of API URLs with their respective response type and
      sample output.
    - Place the `curl` examples in their own section.

commit 28d1bdc4e457cfc44830c8a20013a3f588dafca4
Author: Foster Hangdaan <foster@hangdaan.email>
Date:   Tue Nov 14 20:46:59 2023 -0500

    feat: Added `jsonp` format

    Accepts the `callback` query param for changing the name of the callback function.

commit 126455a3fd96ec3a998847e29cbdcefbd18b16ac
Author: Foster Hangdaan <foster@hangdaan.email>
Date:   Tue Nov 14 20:35:30 2023 -0500

    refactor: Convert `if...else` to `switch`

commit 8945673d5e0644ab6aea8dc268cbaeb12530649c
Author: Foster Hangdaan <foster@hangdaan.email>
Date:   Tue Nov 14 05:50:20 2023 -0500

    doc: Update README.org

    - Added new sections.
    - Moved copyright text into its own section.
    - Some minor edits here and there.

commit f5a6804a9ea57ad52a5f000643661ffd3908dcaa
Author: Foster Hangdaan <foster@hangdaan.email>
Date:   Tue Nov 14 05:11:47 2023 -0500

    Bump version to 0.3.0
This commit is contained in:
Foster Hangdaan 2023-11-14 21:05:52 -05:00
parent 19c6ecd7ff
commit 9418eb04c5
Signed by: foster
GPG key ID: E48D7F49A852F112
3 changed files with 123 additions and 13 deletions

View file

@ -4,13 +4,109 @@
A self-hosted API for obtaining your public IP address. A self-hosted API for obtaining your public IP address.
* Live API Usage
An implementation of the API is available at [[https://ipme.fosterhangdaan.com][ipme.fosterhangdaan.com]].
| URL | Response Type | Sample Output |
|-------------------------------------------------------------+---------------+-------------------------------------|
| https://ipme.fosterhangdaan.com | text | =98.207.254.136= |
| https://ipme.fosterhangdaan.com?format=json | json | ={"ip":"98.207.254.136"}= |
| https://ipme.fosterhangdaan.com?format=jsonp | jsonp | =callback({"ip":"98.207.254.136"})= |
| https://ipme.fosterhangdaan.com?format=jsonp&callback=getIp | jsonp | =getIp({"ip":"98.207.254.136"})= |
** Examples using ~curl~
To get your public IP address in plain text:
#+begin_src shell
curl --silent https://ipme.fosterhangdaan.com
#+end_src
For a response in =json= format:
#+begin_src shell
curl --silent https://ipme.fosterhangdaan.com?format=json
#+end_src
* Self-hosting
** Requirements
- [[https://podman.io/][Podman]] or [[https://www.docker.com/][Docker]] installed
- Ports 80 and 443 opened
- A domain name pointing to the server
For reliable IP address identification, the instance should be hosted on an external server outside of your home or local network.
** Compose setup
The following =compose.yaml= can be used as reference:
#+begin_src yaml
version: "3.9"
volumes:
caddy-data:
external: true
caddy-config:
external: true
networks:
proxy-tier:
driver: bridge
services:
ipme:
image: code.fosterhangdaan.com/foster/ipme:latest
container_name: ipme
restart: unless-stopped
env_file: .env.ipme
networks:
- proxy-tier
caddy:
image: docker.io/library/caddy:2-alpine
container_name: caddy
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./Caddyfile:/etc/caddy/Caddyfile:ro
- caddy-data:/data
- caddy-config:/config
networks:
- proxy-tier
#+end_src
=.env.ipme=
#+begin_src env
RUN_MODE=prod
#+end_src
=Caddyfile=
#+begin_src Caddyfile
# Replace this domain with your own
https://ipme.mydomain.com {
reverse_proxy ipme:8000
}
#+end_src
** Run the services
Run ~podman-compose up~ to start the services.
The API should be available at the domain you selected. For example: =https://ipme.mydomain.com=.
* Contributing * Contributing
Please send patches and bug reports by email to one of the maintainers. See the *Core Maintainers* section for a list of contacts. Please send patches and bug reports by email to one of the maintainers. See the *Core maintainers* section for a list of contacts.
Refer to [[https://git-send-email.io][this guide]] if you are not familiar with sending Git patches over email. Refer to [[https://git-send-email.io][this guide]] if you are not familiar with sending Git patches over email.
* Core Maintainers * Core maintainers
- *Foster Hangdaan* - *Foster Hangdaan*
- Website: [[https://www.fosterhangdaan.com][www.fosterhangdaan.com]] - Website: [[https://www.fosterhangdaan.com][www.fosterhangdaan.com]]
@ -23,8 +119,6 @@ Refer to [[https://git-send-email.io][this guide]] if you are not familiar with
#+attr_html: :width 200px #+attr_html: :width 200px
[[https://static.fosterhangdaan.com/images/agplv3-logo.svg]] [[https://static.fosterhangdaan.com/images/agplv3-logo.svg]]
Copyright \copy 2023 Foster Hangdaan
This program is free software: you can redistribute it and/or modify This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the published by the Free Software Foundation, either version 3 of the
@ -37,3 +131,7 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <https://www.gnu.org/licenses/>.
* Copyright
Copyright \copy 2023 Foster Hangdaan

28
main.ts
View file

@ -30,14 +30,26 @@ const handler = (req: Request): Response => {
const url = new URL(req.url); const url = new URL(req.url);
const format = url.searchParams.get("format"); const format = url.searchParams.get("format");
if (format === "json") { switch(format) {
return new Response(JSON.stringify({ ip: clientIpAddress }), { case "json": {
headers: { return new Response(JSON.stringify({ ip: clientIpAddress }), {
"content-type": "application/json", headers: {
}, "content-type": "application/json",
}); },
} else { });
return new Response(clientIpAddress); }
case "jsonp": {
const parameter = JSON.stringify({ ip: clientIpAddress });
const callback = url.searchParams.get("callback") || "callback";
return new Response(`${callback}(${parameter});`, {
headers: {
"content-type": "application/javascript",
},
});
}
default: {
return new Response(clientIpAddress);
}
} }
} else { } else {
return new Response("Not found", { status: 404 }); return new Response("Not found", { status: 404 });

View file

@ -1,2 +1,2 @@
const version = "0.2.0"; const version = "0.3.0";
export default version; export default version;