From 6875cdfdd6a4cf07ca720c566639e59e7a55e266 Mon Sep 17 00:00:00 2001 From: Jon Friesen Date: Tue, 28 May 2024 15:44:55 -0600 Subject: [PATCH] simplify samples --- apps/curl-geoweather/geoweather.sh | 9 +-- apps/go-geoweather/main.go | 22 +++--- apps/php-geoweather/Dockerfile | 31 --------- apps/php-geoweather/README.md | 70 ------------------- apps/php-geoweather/index.php | 99 -------------------------- apps/python-geoweather/Dockerfile | 10 ++- apps/python-geoweather/app.py | 108 ++++++++++++++++------------- 7 files changed, 80 insertions(+), 269 deletions(-) delete mode 100644 apps/php-geoweather/Dockerfile delete mode 100644 apps/php-geoweather/README.md delete mode 100644 apps/php-geoweather/index.php diff --git a/apps/curl-geoweather/geoweather.sh b/apps/curl-geoweather/geoweather.sh index 47af0e0..118f8e0 100755 --- a/apps/curl-geoweather/geoweather.sh +++ b/apps/curl-geoweather/geoweather.sh @@ -3,11 +3,12 @@ # Function to get public IP get_public_ip() { local ip - ip=$(curl -s https://httpbin.org/ip | jq -r .origin) + ip=$(curl -s icanhazip.com) if [ -z "$ip" ]; then echo "Unable to get public IP" exit 1 fi + echo "$ip" } @@ -15,7 +16,7 @@ get_public_ip() { get_location() { local ip="$1" local location - location=$(curl -s "http://ip-api.com/json/{$ip}") + location=$(curl -s "https://ipwho.is/{$ip}?fields=country,city,latitude,longitude") if [ -z "$location" ]; then echo "Unable to get location" exit 1 @@ -50,8 +51,8 @@ main() { local city country latitude longitude city=$(echo "$location" | jq -r .city) country=$(echo "$location" | jq -r .country) - latitude=$(echo "$location" | jq -r .lat) - longitude=$(echo "$location" | jq -r .lon) + latitude=$(echo "$location" | jq -r .latitude) + longitude=$(echo "$location" | jq -r .longitude) echo -e "\n2. Location fetched for IP $public_ip:\n\t$city, $country\n\t($latitude, $longitude)" if [ -z "$latitude" ] || [ -z "$longitude" ]; then diff --git a/apps/go-geoweather/main.go b/apps/go-geoweather/main.go index f5987d8..62d6046 100644 --- a/apps/go-geoweather/main.go +++ b/apps/go-geoweather/main.go @@ -4,19 +4,17 @@ import ( "encoding/json" "fmt" "html/template" + "io" "log" "net/http" + "strings" ) -type IPResponse struct { - Origin string `json:"origin"` -} - type LocationResponse struct { City string `json:"city"` CountryName string `json:"country_name"` - Latitude float64 `json:"lat"` - Longitude float64 `json:"lon"` + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` } type WeatherResponse struct { @@ -26,22 +24,22 @@ type WeatherResponse struct { } func getPublicIP() (string, error) { - resp, err := http.Get("https://httpbin.org/ip") + resp, err := http.Get("https://icanhazip.com") if err != nil { return "", fmt.Errorf("unable to get public IP: %v", err) } defer resp.Body.Close() - var ipResp IPResponse - if err := json.NewDecoder(resp.Body).Decode(&ipResp); err != nil { - return "", fmt.Errorf("unable to parse IP response: %v", err) + b, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("reading response body: %w", err) } - return ipResp.Origin, nil + return strings.TrimSpace(string(b)), nil } func getLocation(ip string) (LocationResponse, error) { - url := fmt.Sprintf("http://ip-api.com/json/%s", ip) + url := fmt.Sprintf("https://ipwho.is/%s?fields=country,city,latitude,longitude", ip) resp, err := http.Get(url) if err != nil { return LocationResponse{}, fmt.Errorf("unable to get location: %v", err) diff --git a/apps/php-geoweather/Dockerfile b/apps/php-geoweather/Dockerfile deleted file mode 100644 index a31f112..0000000 --- a/apps/php-geoweather/Dockerfile +++ /dev/null @@ -1,31 +0,0 @@ -# Use an official PHP runtime as a parent image -FROM php:7.4-apache - -# Get latest CA's -ARG TOKEN -RUN apt-get update && \ - apt-get install -y curl ca-certificates && \ - if [ -n "$TOKEN" ]; then \ - curl -s https://api.qpoint.io/deploy/certificate -H "Authorization: Bearer $TOKEN" > /usr/local/share/ca-certificates/qpoint-ca.crt && \ - update-ca-certificates; \ - fi && \ - rm -rf /var/lib/apt/lists/* - -# Copy the current directory contents into the container at /var/www/html -COPY . /var/www/html/ - -# Install necessary extensions -RUN docker-php-ext-install json - -# Set the ServerName directive globally to suppress the warning -RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf - -# Update the Apache configuration to listen on port 4000 -RUN sed -i 's/Listen 80/Listen 4000/' /etc/apache2/ports.conf && \ - sed -i 's/:80/:4000/' /etc/apache2/sites-available/000-default.conf - -# Make port 4000 available to the world outside this container -EXPOSE 4000 - -# Start the Apache server -CMD ["apache2-foreground"] diff --git a/apps/php-geoweather/README.md b/apps/php-geoweather/README.md deleted file mode 100644 index ff68abf..0000000 --- a/apps/php-geoweather/README.md +++ /dev/null @@ -1,70 +0,0 @@ - -# GeoWeather App (php) - -A simple demo application that displays the weather for the user's current location based on their IP address. The app is built using `php` and accepts `HTTP_PROXY` and `HTTPS_PROXY` environment variables for interacting with QPoint. - -## Prerequisites - -- Git -- Docker - -## Running the Application - -### 1. Setup a Qpoint Qproxy -This demo utilizes the Qpoint Control Plane and requires a free Qpoint account. - -1. Head over to [Qpoint](https://qpoint.io) and sign up for an account. -2. Click the `+ Go` button on the nav bar. -3. Select the `Deploy Qproxy` option. -4. Select `Docker`. -5. Copy the provided Docker run command and execute it in a terminal. -6. Set the Address, `localhost` is probably fine for this example. - -At this point, you'll have a running Qpoint proxy ready to take on traffic! - -### 2. Connect an App to a Transparent Qpoint Proxy - -1. On the [Qpoint Dashboard](https://qpoint.io), select `+ Go`. -2. Select `Connect an App` on the right side of the menu. -3. Select the `Proxy Environment Variable` option. -4. Select the `Transparent Proxy` option. -5. Make a note of the HTTP and HTTPS proxy URLs. - -### 3. Clone the Repository - -``` -git clone https://github.com/qpoint-io/demos.git -cd demos/apps/php-geoweather -``` - -### 4. Build & Start the Docker Container -Within an app directory of your choosing, run the following command to build and run the application. - -> Note: If you used an address other than "localhost," make sure to update those values in this command. - -``` -docker build -t php-geoweather . && \ - docker run -it --rm \ - --network host \ - -e HTTP_PROXY=http://localhost:18080 \ - -e HTTPS_PROXY=http://localhost:18443 \ - php-geoweather -``` - -> Note: This command uses the host machine's network to provide access to the published ports in the Qpoint container. - -### 5. Test the App - -Navigate to [localhost:4000](http://localhost:4000) and check the weather for your location. - -### 6. Review Traffic - -This app reaches out to various APIs to retrieve your remote IP, geo-IP location, and weather data. Navigating to the [Qpoint Traffic Dashboard](https://qpoint.io) will display the domain URLs being accessed by the application. Each domain is clickable and will let you dive into the traffic for each. - -## License - -This project is licensed under the Apache-2.0 License. diff --git a/apps/php-geoweather/index.php b/apps/php-geoweather/index.php deleted file mode 100644 index 6c21258..0000000 --- a/apps/php-geoweather/index.php +++ /dev/null @@ -1,99 +0,0 @@ - - - - - - GeoWeather App - - -

Welcome to the GeoWeather App (PHP)

-
- -
- - -

Weather for ,

-

Temperature: °C

- Back to home - - - - diff --git a/apps/python-geoweather/Dockerfile b/apps/python-geoweather/Dockerfile index e9abd27..e560a72 100644 --- a/apps/python-geoweather/Dockerfile +++ b/apps/python-geoweather/Dockerfile @@ -1,15 +1,13 @@ # Use an official Python runtime as a parent image -FROM python:3.12-slim +FROM python:3.12-alpine # Get latest CA's ARG TOKEN -RUN apt-get update && \ - apt-get install -y curl ca-certificates && \ +RUN apk --no-cache add curl ca-certificates && \ if [ -n "$TOKEN" ]; then \ curl -s https://api.qpoint.io/deploy/certificate -H "Authorization: Bearer $TOKEN" > /usr/local/share/ca-certificates/qpoint-ca.crt && \ update-ca-certificates; \ - fi && \ - rm -rf /var/lib/apt/lists/* + fi # Set the working directory to /app WORKDIR /app @@ -18,7 +16,7 @@ WORKDIR /app COPY . . # Install any needed packages specified in requirements.txt -RUN pip install Flask[async] requests httpx h2 +RUN pip install flask requests # Make port 4000 available to the world outside this container EXPOSE 4000 diff --git a/apps/python-geoweather/app.py b/apps/python-geoweather/app.py index 145e310..68ff862 100644 --- a/apps/python-geoweather/app.py +++ b/apps/python-geoweather/app.py @@ -1,31 +1,49 @@ from flask import Flask, request, render_template_string -import httpx +import requests import logging -app = Flask(__name__) - # Configure logging -logging.basicConfig(level=logging.DEBUG) +logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') + +app = Flask(__name__) -async def get_public_ip(): +def get_public_ip(): try: - async with httpx.AsyncClient() as client: - response = await client.get('https://httpbin.org/ip') - return response.json()['origin'] - except Exception as e: - return "Unable to get public IP: " + str(e) + response = requests.get('https://icanhazip.com') + response.raise_for_status() # Will raise an HTTPError for bad responses + return response.text.strip() + except requests.HTTPError as http_err: + logging.error(f'HTTP error occurred: {http_err}') # HTTP error + return f"Unable to get public IP: HTTP error occurred: {http_err}" + except Exception as err: + logging.error(f'Other error occurred: {err}') # Other errors + return f"Unable to get public IP: Other error occurred: {err}" -async def get_location(ip): - url = f"http://ip-api.com/json/{ip}" - async with httpx.AsyncClient() as client: - response = await client.get(url) +def get_location(ip): + url = f"https://ipwho.is/{ip}?fields=country,city,latitude,longitude" + try: + response = requests.get(url) + response.raise_for_status() return response.json() + except requests.HTTPError as http_err: + logging.error(f'HTTP error occurred while fetching location: {http_err}') + return {'error': f"HTTP error occurred: {http_err}"} + except Exception as err: + logging.error(f'Error fetching location: {err}') + return {'error': f"Other error occurred: {err}"} -async def get_weather(lat, lon): +def get_weather(lat, lon): url = f"https://api.open-meteo.com/v1/forecast?latitude={lat}&longitude={lon}¤t=temperature_2m&forecast_days=1" - async with httpx.AsyncClient() as client: - response = await client.get(url) + try: + response = requests.get(url) + response.raise_for_status() return response.json() + except requests.HTTPError as http_err: + logging.error(f'HTTP error occurred while fetching weather: {http_err}') + return {'error': f"HTTP error occurred: {http_err}"} + except Exception as err: + logging.error(f'Error fetching weather: {err}') + return {'error': f"Other error occurred: {err}"} @app.route('/') def index(): @@ -38,7 +56,7 @@ def index():

Welcome to the GeoWeather App (Python)

-
+
@@ -47,39 +65,35 @@ def index(): return render_template_string(html) @app.route('/weather', methods=['POST']) -async def weather(): - logging.debug("Starting weather function") +def weather(): + public_ip = get_public_ip() - public_ip = await get_public_ip() - logging.debug(f"Public IP fetched: {public_ip}") + if "Unable to get public IP" in public_ip: + return f"

Error: {public_ip}

" - location = await get_location(public_ip) - logging.debug(f"Location fetched for IP {public_ip}: {location}") + location = get_location(public_ip) + if 'error' in location: + return f"

Error fetching location data for IP {public_ip}: {location['error']}

" - if 'lat' in location and 'lon' in location: - weather = await get_weather(location['lat'], location['lon']) - logging.debug(f"Weather fetched for location {location['lat']}, {location['lon']}: {weather}") + weather = get_weather(location['latitude'], location['longitude']) + if 'error' in weather: + return f"

Error fetching weather data: {weather['error']}

" - weather_html = f""" - - - - - Weather Result - - -

Weather for {location['city']}, {location['country']} (Python)

-

Temperature: {weather['current']['temperature_2m']}°C

- Back to home - - - """ - return render_template_string(weather_html) - else: - logging.error(f"Error fetching location data for IP: {public_ip}") - return f"Error fetching location data for IP" + weather_html = f""" + + + + + Weather Result + + +

Weather for {location['city']}, {location['country']}

+

Temperature: {weather['current']['temperature_2m']}°C

+ Back to home + + + """ + return render_template_string(weather_html) if __name__ == "__main__": - import asyncio app.run(host='0.0.0.0', port=4000) -