# Ignition - create simple HTTP Server

**URL:** <https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695>\
**Category:** Ignition\
**Tags:** scripting\
**Created:** [January 24, 2024, 2:27pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695 "2024-01-24T14:27:06Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![davee\_s](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@davee\_s](https://forum.inductiveautomation.com/u/davee_s)\
**Post date:** [January 24, 2024, 2:27pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/1 "2024-01-24T14:27:06Z")

</div>

Hello guys, I am trying to create a simple HTTP Server in Ignition that listen on a port for http requests like GET, POST ecc... and send back a response.  
Is there a way to implement this in Python or with external libraries like Flask for example?  
I attach the example code

```auto
from flask import Flask, jsonify

app = Flask( __name__ )

@app.route('/')
def hello():
    return "Hello, world!"

@app.route('/api/data', methods=['GET'])
def get_data():
    data = {"key": "value"}
    return jsonify(data)

if __name__ == ' __main__':
    app.run(port=8000)

```

---

<div class="post-metadata">

**Author:** ![kcollins](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kcollins/32/19646_2.png) [@kcollins](https://forum.inductiveautomation.com/u/kcollins)\
**Post date:** [January 24, 2024, 2:35pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/2 "2024-01-24T14:35:30Z")

</div>

I think you'll achieve this most easily with the [WebDev module](https://docs.inductiveautomation.com/display/DOC81/WebDev+Module), that is exactly what it is intended for.

---

<div class="post-metadata">

**Author:** ![davee\_s](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@davee\_s](https://forum.inductiveautomation.com/u/davee_s)\
**Post date:** [January 24, 2024, 2:37pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/3 "2024-01-24T14:37:24Z")

</div>

Hello @kcollins thanks for your reply. I know there is a dedicated module but for now we can't buy the license for it, so I was thinking about to do this by script if possible

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 24, 2024, 4:49pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/4 "2024-01-24T16:49:12Z")

</div>

Basically, no. There's no way via scripting to introduce something durable enough that isn't also a massive memory leak.

If you really want to trade engineering time for a solution, you can always develop a custom module that replicates the "load a servlet" part of the Webdev module:

> **[GitHub - inductiveautomation/ignition-sdk-examples: Ignition SDK Example...](https://github.com/inductiveautomation/ignition-sdk-examples)**
>
> Ignition SDK Example Projects. Contribute to inductiveautomation/ignition-sdk-examples development by creating an account on GitHub.

Custom modules can do whatever you want (except on Edge) and are free.

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [January 24, 2024, 5:18pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/5 "2024-01-24T17:18:19Z")

</div>

> [@paul-griffith](#):
>
> (except on Edge and Maker)

What can't they do on Maker?

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [January 24, 2024, 5:25pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/6 "2024-01-24T17:25:11Z")

</div>

You're right - Maker is just an opt-in flag on the hook. I thought there was some third party module restriction, but the only difference is which _first_ party modules will load.

---

<div class="post-metadata">

**Author:** ![davee\_s](https://avatars.discourse-cdn.com/v4/letter/d/e47774/32.png) [@davee\_s](https://forum.inductiveautomation.com/u/davee_s)\
**Post date:** [January 25, 2024, 10:18am UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/7 "2024-01-25T10:18:43Z")

</div>

Thanks @paul-griffith thought there was a way to achieve this via script. If I have enough time, I will take your suggestion into consideration

---

<div class="post-metadata">

**Author:** ![Samuel\_Sueur](https://avatars.discourse-cdn.com/v4/letter/s/e36b37/32.png) [@Samuel\_Sueur](https://forum.inductiveautomation.com/u/Samuel_Sueur)\
**Post date:** [July 11, 2024, 7:14am UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/8 "2024-07-11T07:14:46Z")

</div>

Hi @paul-griffith

How big of a memory leak are we really talking about ?

I have an external application that needs to send its data to Ignition every hour via a POST request, I've created a simple HTTP server (code below) that runs in Ignition.

> **HTTP server code**
>
> ```python
> from com.sun.net.httpserver import HttpServer, HttpHandler, HttpExchange
> from java.net import InetSocketAddress
> from java.io import IOException
> from java.io import InputStreamReader
> from java.io import BufferedReader
> from java.lang import StringBuilder
> 
> # Define a simple HTTP handler
> class MyHandler(HttpHandler):
> def handle(self, exchange):
> try:
> if exchange.getRequestMethod().upper() == "POST":
> 	
> length = exchange.getRequestHeaders().getFirst("Content-length")
> content_length = int(length) if length else 0	
> if content_length > 0:
> 					
> input_stream = exchange.getRequestBody()
> isr = InputStreamReader(input_stream, 'utf-8')
> reader = BufferedReader(isr)
> buffer = StringBuilder()
> 					
> while True:
> line = reader.readLine()
> if line is None:
> break
> buffer.append(line)
> 					
> post_data = buffer.toString()
> system.util.getLogger("HTTP_SERVER").info("Received POST data:"+ str(post_data))
> 				
> input_stream.close()
> 					
> 					
> response = "Received POST data: " + post_data
> exchange.sendResponseHeaders(200, len(response))
> outputStream = exchange.getResponseBody()
> outputStream.write(response.encode('utf-8'))
> outputStream.close()
> if exchange.getRequestMethod().upper() == "GET":
> response = "Hello, World!"
> exchange.sendResponseHeaders(200, len(response))
> outputStream = exchange.getResponseBody()
> outputStream.write(response.encode('utf-8'))
> outputStream.close()
> 			
> except IOException as e:
> e.printStackTrace()
> 
> # Function to start the HTTP server
> def start_server():
> server_address = InetSocketAddress(7999)
> http_server = HttpServer.create(server_address, 0)
> http_server.createContext("/", MyHandler())
> http_server.setExecutor(None) # Use the default executor
> http_server.start()
> system.util.globals["http_server"] = http_server
> system.util.getLogger("HTTP_SERVER").info("HTTP server started...")
> print("HTTP server started on port 7999")
> 
> def init():
> # Run the server
> if "http_server" in system.util.globals and system.util.globals["http_server"] is not None:
> system.util.globals["http_server"].stop(0)
> print("server stopped")
> start_server()
> 
> 	
> def close():
> if "http_server" in system.util.globals and system.util.globals["http_server"] is not None:
> system.util.globals["http_server"].stop(0)
> 
> ```

What could happen ? If the thread runs for too long, it could take up the whole memory ?  
Considering the fact that the application sends its data every hour, would the memory leak be under control if I restart this server say every half an hour or so ?

I have a hard time justifying the use of the WebDev module to my client considering only one client will send its data, and it's only once an hour.

Thanks

---

<div class="post-metadata">

**Author:** ![PRAMANJ](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pramanj/32/66935_2.png) [@PRAMANJ](https://forum.inductiveautomation.com/u/PRAMANJ)\
**Post date:** [July 11, 2024, 1:28pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/9 "2024-07-11T13:28:53Z")

</div>

We had tried a NODEJS server connected with Ignition in TCP/IP socket thru scripts and clients communicating with NODEJS server thru REST APIs. Please see [demo link](https://youtu.be/YrcScJZWeoU). Perhaps you can try something like that! Or simply let you application connect to Ignition on TCP/IP socket if its not a web application.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [July 11, 2024, 2:19pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/10 "2024-07-11T14:19:33Z")

</div>

If you're caching any custom class in system.util.globals, you're implicitly storing the entire Jython interpreter state (and all of its associated memory usage, which includes all parsed project script libraries, all parsed third party libraries, etc), for at least as long as that instance is alive.

Your server creation and shutdown code is also racy - multiple threads could be running script initialization at once (because we create and shut down the whole Jython lifecycle all the time, whenever you change any script related resources), so one lifecycle might pass the first if at the same time as another and both end up attempting to create a server (and bind to the same address) at the same time. You should use Python's builtin setdefault to atomically update the dictionary.

If you really can restart the server every hour, then, sure, I guess you're successfully band-aid patching a memory leak. How maintainable is that in six months, in five years, etc?

---

<div class="post-metadata">

**Author:** ![Samuel\_Sueur](https://avatars.discourse-cdn.com/v4/letter/s/e36b37/32.png) [@Samuel\_Sueur](https://forum.inductiveautomation.com/u/Samuel_Sueur)\
**Post date:** [July 11, 2024, 6:36pm UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/11 "2024-07-11T18:36:06Z")

</div>

Thanks a lot for your reply, you've convinced myself and the client that the WebDev module would prove much more reliable than this crafty solution of mine, also far from being an expert so thanks for the tips regarding python's setdefault!

---

<div class="post-metadata">

**Author:** ![PRAMANJ](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pramanj/32/66935_2.png) [@PRAMANJ](https://forum.inductiveautomation.com/u/PRAMANJ)\
**Post date:** [July 12, 2024, 6:20am UTC](https://forum.inductiveautomation.com/t/ignition-create-simple-http-server/84695/12 "2024-07-12T06:20:45Z")

</div>

WebDev is worth, rather than trying some round about solution to save fraction of Ignition cost's and writing some bug ridden code of our own !
