import http.server
import urllib.parse
import numpy as np
import plotly.graph_objects as go
import sys
import os
import multiprocessing
import signal
import atexit
PORT = 8000
pid_file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'server.pid')
html_form = '''
Sinusoidal Plot
{plot}
'''
class PlotlyHandler(http.server.BaseHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(html_form.format(plot='').encode('utf-8'))
def do_POST(self):
content_length = int(self.headers['Content-Length'])
post_data = self.rfile.read(content_length)
params = urllib.parse.parse_qs(post_data.decode('utf-8'))
a = float(params.get('a', [1])[0])
w = float(params.get('w', [10])[0])
tmin = float(params.get('tmin', [0])[0])
tmax = float(params.get('tmax', [10])[0])
tstep = 0.1
t = np.arange(tmin, tmax + tstep, tstep)
y = a * np.sin(w * t)
fig = go.Figure()
fig.add_trace(go.Scatter(x=t, y=y, mode='lines', name='sinusoidal'))
fig.update_layout(title='Sinusoidal Plot', xaxis_title='Time (t)', yaxis_title='Amplitude (a*sin(w*t))')
plot_html = fig.to_html(full_html=False)
self.send_response(200)
self.send_header("Content-type", "text/html")
self.end_headers()
self.wfile.write(html_form.format(plot=plot_html).encode('utf-8'))
def run_cgi():
post_data = sys.stdin.read()
params = urllib.parse.parse_qs(post_data)
a = float(params.get('a', [1])[0])
w = float(params.get('w', [10])[0])
tmin = float(params.get('tmin', [0])[0])
tmax = float(params.get('tmax', [10])[0])
tstep = 0.1
t = np.arange(tmin, tmax + tstep, tstep)
y = a * np.sin(w * t)
fig = go.Figure()
fig.add_trace(go.Scatter(x=t, y=y, mode='lines', name='sinusoidal'))
fig.update_layout(title='Sinusoidal Plot', xaxis_title='Time (t)', yaxis_title='Amplitude (a*sin(w*t))')
plot_html = fig.to_html(full_html=False)
print("Content-Type: text/html\n")
print(html_form.format(plot=plot_html))
def start_server():
server = http.server.HTTPServer(('0.0.0.0', PORT), PlotlyHandler)
print(f"Server running on port {PORT}")
signal.signal(signal.SIGTERM, handle_exit)
signal.signal(signal.SIGINT, handle_exit)
server.serve_forever()
def handle_exit(*args):
if os.path.exists(pid_file_path):
os.remove(pid_file_path)
print("Clean exit: pid_file removed")
sys.exit(0)
def stop_server():
if os.path.exists(pid_file_path):
with open(pid_file_path, 'r') as f:
pid = int(f.read().strip())
try:
os.kill(pid, signal.SIGTERM)
os.remove(pid_file_path)
print("Server stopped")
except OSError:
print("Error stopping server")
else:
print("Server is not running")
def run_server_process():
process = multiprocessing.Process(target=start_server)
process.start()
with open(pid_file_path, 'w') as f:
f.write(str(process.pid))
print(f"Server started with PID {process.pid}")
if __name__ == '__main__':
if len(sys.argv) < 2:
print("Usage: python server.py [start|stop|run]")
sys.exit(1)
mode = sys.argv[1]
if mode == 'start':
atexit.register(handle_exit)
run_server_process()
elif mode == 'stop':
stop_server()
elif mode == 'run':
run_cgi()
else:
print("Unknown mode:", mode)
sys.exit(1)