How to access an API from an IoT Edge Module

Roshan Thomas(UST,IN) 0 Reputation points
2023-04-17T12:20:43.28+00:00

Hi, I am trying to access an API from IoT Edge Module hoisted in Azure AppServices in port 8000, but I am not able to access it. Please find the steps:

  1. Exposed 8000 port in the docker file User's image
    1. Set the up the environment variables in IoT Edge Module User's image
    2. Configured the following container create options: User's image

The modules get deployed successfully. But the module throws exception as :


Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 710, in urlopen
    chunked=chunked,
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 386, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 1042, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.7/site-packages/urllib3/connection.py", line 429, in connect
    tls_in_tls=tls_in_tls,
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 450, in ssl_wrap_socket
    sock, context, tls_in_tls, server_hostname=server_hostname
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.7/ssl.py", line 423, in wrap_socket
    session=session
  File "/usr/local/lib/python3.7/ssl.py", line 870, in _create
    self.do_handshake()
  File "/usr/local/lib/python3.7/ssl.py", line 1139, in do_handshake
    self._sslobj.do_handshake()
ConnectionResetError: [Errno 104] Connection reset by peer

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/requests/adapters.py", line 499, in send
    timeout=timeout,
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 788, in urlopen
    method, url, error=e, _pool=self, _stacktrace=sys.exc_info()[2]
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/retry.py", line 550, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/usr/local/lib/python3.7/site-packages/urllib3/packages/six.py", line 769, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 710, in urlopen
    chunked=chunked,
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 386, in _make_request
    self._validate_conn(conn)
  File "/usr/local/lib/python3.7/site-packages/urllib3/connectionpool.py", line 1042, in _validate_conn
    conn.connect()
  File "/usr/local/lib/python3.7/site-packages/urllib3/connection.py", line 429, in connect
    tls_in_tls=tls_in_tls,
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 450, in ssl_wrap_socket
    sock, context, tls_in_tls, server_hostname=server_hostname
  File "/usr/local/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 493, in _ssl_wrap_socket_impl
    return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
  File "/usr/local/lib/python3.7/ssl.py", line 423, in wrap_socket
    session=session
  File "/usr/local/lib/python3.7/ssl.py", line 870, in _create
    self.do_handshake()
  File "/usr/local/lib/python3.7/ssl.py", line 1139, in do_handshake
    self._sslobj.do_handshake()
urllib3.exceptions.ProtocolError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "./utility_api.py", line 49, in 
Azure IoT Edge
Azure IoT Edge
An Azure service that is used to deploy cloud workloads to run on internet of things (IoT) edge devices via standard containers.
548 questions
{count} votes

1 answer

Sort by: Most helpful
  1. LeelaRajeshSayana-MSFT 13,871 Reputation points
    2023-04-19T03:13:30.51+00:00

    Hi @Roshan Thomas(UST,IN) Have you tried to access the App service Rest API end point from within the Python code of your module using HTTP request? I have set up a Python Edge module and accessed the Rest API end point hosted in Azure App. I have set up the App Service Rest API using the tutorial Host a RESTful API with CORS in Azure App Service. I do not have to open any ports explicitly on the IoT Edge module container.

    Here is my docker file

    FROM amd64/python:3.7-slim-buster
    
    WORKDIR /app
    
    COPY requirements.txt ./
    RUN pip install -r requirements.txt
    
    COPY . .
    
    CMD [ "python3", "-u", "./main.py" ]
    
    

    I have left the create options as default. Please find the below snippet showing the create options section from deployment.template.json file

    "createOptions": {
                    "HostConfig": {
                      "PortBindings": {
                        "5671/tcp": [
                          {
                            "HostPort": "5671"
                          }
                        ],
                        "8883/tcp": [
                          {
                            "HostPort": "8883"
                          }
                        ],
                        "443/tcp": [
                          {
                            "HostPort": "443"
                          }
                        ]
                      }
                    }
                  }
    

    Within the main method of the main.py, I have called the Rest API endpoint using requests and could access the data. Please find the below snippet to find the code I have tested

    api_url = "http://<app-name>.azurewebsites.net/api/todo"
    
    # Set the request headers
    headers = {"Content-Type": "application/json"}
    
    # Set the request body (if applicable)
    body = {"key": "value"}
    
    response = requests.get(api_url, headers=headers, json=body)
    
    if response.status_code == 200:
        # Read the response content as a string
        response_json = response.json()
        for item in response_json:
        print(item["id"], item["name"], item["isComplete"])
    
    else:
        # Handle the error response in your Python script
        print(f"Error calling API: {response.status_code}")
        
    
    

    I have created a IoT Hub device client within the app and could route the data I have received from the API to an Azure storage account. I appreciate it if you can give the above method a try and let me know if that helps.

    If your App service Rest API uses any Authorization or if it is behind a proxy server, test the API from the Postman and make sure you include the correct end point and the authorization headers to the request.

    Can you test if you can ping the Azure App service end point from the VM where your IoT Edge modules are deployed? You can run the following command ping <app-name>.scm.azurewebsites.net from the bash of the VM and see if you can reach the App service end point. If you cannot ping the IP, enable the ICMP protocol on the VM and see if that helps. User's image

    If you still see the same error in the module, place time.sleep(0.01) in the code before right before making the Http request. Please refer the following sample for reference

    AI ConvertCopy

    time.sleep(0.01)
    response = requests.get(api_url, headers=headers, json=body)
    
    

    Let us know if you run into any issues or need any additional assistance in the comments below.

    0 comments No comments