Commit c003d969 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Initial commit

parents
FROM python:3.9-buster
COPY requirements.txt ./
RUN pip install -r requirements.txt --extra-index-url https://www.ict.inaf.it/gitlab/api/v4/projects/670/packages/pypi/simple
COPY server.py index.html script.js ./
ENTRYPOINT ["python", "server.py"]
# Coords Service
Toy Python server using [Coords Library](https://www.ict.inaf.it/gitlab/ci-intro/coords-library) to demonstrate GitLab CI features.
favicon.ico

1022 Bytes

<html>
<head>
<title>Coordinates calculator</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-eOJMYsd53ii+scO/bJGFsiCZc+5NDVN2yr8+0RDqr0Ql0h+rP48ckxlpbzKgwra6" crossorigin="anonymous" />
<!-- Fetch API polyfill, for supporting Internet Explorer -->
<script src="https://cdn.jsdelivr.net/npm/fetch-polyfill@0.8.2/fetch.min.js"></script>
<style>
.hide { display: none; }
.loading {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.7);
z-index: 100000;
}
.spinner-wrapper {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
width: 100%;
}
.spinner-border {
width: 3rem; height: 3rem;
}
</style>
</head>
<body>
<div class="container">
<div class="row mt-5">
<div class="col text-center">
<h2>Coordinates for #LOCATION_NAME#</h2>
<p class="fw-light">Using coords-library #LIB_VERSION#</p>
</div>
</div>
<div class="row">
<div class="col-6 offset-3">
<div class="input-group mt-3 mb-3">
<input type="text" class="form-control" id="object_name" placeholder="Object name" aria-label="Object name" aria-describedby="get_coordinates">
<button class="btn btn-primary" type="button" id="get_coordinates">Get coordinates</button>
</div>
<div class="alert alert-danger hide" role="alert" id="error">
</div>
<div class="row hide" id="result">
<div class="col">
<ul id="result-list">
<!-- results go here -->
</ul>
</div>
</div>
</div>
</div>
</div>
<div id="loading" class="loading hide">
<div class="spinner-wrapper">
<div class="spinner-border text-info" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
</html>
\ No newline at end of file
function getCoordinates() {
// Previous results cleanup
document.getElementById('loading').classList.remove('hide');
document.getElementById('result').classList.add('hide');
document.getElementById('result-list').innerHTML = '';
document.getElementById('error').classList.add('hide');
// Retrieve object name
let objectName = document.getElementById('object_name').value;
// Call the server
fetch('coords?object=' + objectName)
.then(response => response.json())
.then(data => {
if (typeof data['error'] === 'undefined') {
// Build results list
let resultsHTML = '';
for (let key in data) {
resultsHTML += '<li><strong>' + key + '</strong>: ' + data[key] + '</li>';
}
document.getElementById('result-list').innerHTML = resultsHTML;
document.getElementById('result').classList.remove('hide');
} else {
// Show error
let errorElement = document.getElementById('error');
errorElement.classList.remove('hide');
errorElement.innerText = data['error'];
}
})
.finally(() => {
document.getElementById('loading').classList.add('hide');
});
}
// Event handlers
document.getElementById('get_coordinates').onclick = getCoordinates;
document.getElementById('object_name').onkeydown = function(event) {
// Enter key event
if(event.keyCode === 13) {
getCoordinates();
}
};
import http.server
import socketserver
import urllib.parse as urlparse
from urllib.parse import parse_qs
from importlib.metadata import version
import json
import sys
import traceback
import argparse
import coords
class CoordsHttpRequestHandler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
try:
if self.path == '/':
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
# Open HTML page and replace placeholders
content = open('index.html', 'r').read()
location_name = coords.get_location_name(location_id)
content = content.replace('#LOCATION_NAME#', location_name)
content = content.replace('#LIB_VERSION#', version('coordslib'))
self.wfile.write(bytes(content, 'utf8'))
return
elif self.path.startswith('/coords'):
# extract 'object' query parameter from URL
parsed = urlparse.urlparse(self.path)
object_name = parse_qs(parsed.query)['object'][0]
# call coords library
result = coords.get_coords(object_name, location_id)
self.send_response(200)
self.send_json_response(result)
return
except Exception as ex:
print(traceback.format_exc(), file=sys.stderr)
# send error response
self.send_response(500)
self.send_json_response({'error': str(ex)})
return
# default server GET implementation (returns file or 404)
return http.server.SimpleHTTPRequestHandler.do_GET(self)
def send_json_response(self, data):
self.send_header('Content-type', 'application/json')
self.end_headers()
# write JSON data in HTTP response body
self.wfile.write(bytes(json.dumps(data) + '\n', 'utf8'))
parser = argparse.ArgumentParser(description='Simple HTTP server that displays a form '
'to get astronomical coordinates for a given location')
parser.add_argument('port', type=int, nargs=1, help='server port')
parser.add_argument('location_id', type=str, nargs=1, help='astropy observatory/site identifier')
args = parser.parse_args()
port = args.port[0]
location_id = args.location_id[0]
# Create an object of the above class
handler_object = CoordsHttpRequestHandler
# Avoid 'address already in use' error on server restart
socketserver.TCPServer.allow_reuse_address = True
coords_server = socketserver.TCPServer(("", port), handler_object)
# Start the server
coords_server.serve_forever()
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment