Best Way to send HTTP 200 OK code back to client

MiServer is Dyalog's APL-based web development framework

Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Mon Jan 07, 2019 8:58 am

- I looked at the HttpUtils Request and Response methods and couldn't get them to work for me (I get lots of uncaught value and domain errors) , and also at the MiServer Restful info and couldn't figure out how to get that to work. I need to receive HTTP Get Rest calls from a client in my house. I can receive the Rest strings and can send Rest commands back to it, but I haven't figured out how to provide an HTTP acknowledgement that the APL "server" has received and accepted the REST command string from the lighting controller. The lighting controller doesn't seem to request a socket connection. I am using the Conga 3.1 HTTP library to receive and separate the HTTP calls. when I try to SEND using the same connection ID I am using for the server, I get a 1008 ERR_Invalid_Object message.

This is a very predictable environment so I should be able to get buy without a lot of bells and whistles.

The Conga 3.1 info and the MiServer documentation get close to giving an example of how to do this -- bit unfortunately not close enough for me!

I am doing the development on a windows machine but the target is a Raspberry Pi.

I am just looking for an insight into how to send the acknowledgment back to the right place, and maybe a worked example. I haven't made the investment to be able to follow the object class methods in the MiServer world.

Thanks for any illumination!
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Mon Jan 07, 2019 8:13 pm

Never mind and sorry for any inconvenience. I found the answer in an old Conga User guide -- it may well be in the current one also. For anyone as oblivious as I was, The key is to use the object provided by the iConga.Wait response (when the HTTPGet is received to SEND the response.
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Mon Jan 07, 2019 8:46 pm

Just FYI, the needed insight came from the "Parallel Commands" section of the Conga manual that remains in the current version.
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby Brian|Dyalog on Tue Jan 08, 2019 3:10 pm

Hi Tom,

It sounds like you're trying to implement a simple HTTP server. Conga 3.1 has some templates for a few flavors of HTTP servers. There's a bit of information in the section labeled "Directory HttpServers" on page 11 of the Conga Supplement document Conga Supplement document. However, when I reread that section, it's clear we need more explanation (and we're working on that for Dyalog version 17.1). There's more, lower level, information on Conga's HTTP support beginning on page 12 of the same document.

If you're able to use one of the templates (DocHttpRequest for instance), then a lot of the "work" is done for you and you really only need to override the onHtmlReq method to parse and respond to the request.

Here's a simple example building a trivial HTTP server that just sends back information about the request.

      ⍝ start with a clean slate 
)clear
clear ws

⍝ copy Conga's Conga namespace
)copy conga Conga
C:\Program Files\Dyalog\Dyalog APL-64 17.0 Unicode\ws\conga.dws saved Tue Oct 16 10:21:16 2018

⍝ load HttpCommand so we can sent a test request
]load HttpCommand
#.HttpCommand

⍝ load the DocHttpRequest template
]load [dyalog]/samples/conga/httpservers/DocHttpRequest
#.DocHttpRequest

⍝ create a new server based on DocHttpRequest that listens on port 8088
myServer←Conga.Srv 8088 DocHttpRequest

⍝ start the server
myServer.Start

⍝ now send a request (you could also open a browser and navigate to 127.0.0.1:8088)
⎕←response←HttpCommand.Get'127.0.0.1:8088?testing=1'
[rc: 0 | msg: "" | HTTP Status: 200 "ok" | ⍴Data: 312]

⍝ here are the headers sent back by the server
response.Headers
content-length 312
date Tue, 08 Jan 2019 15:01:06 GMT
server ClassyDyalog
content-type text/html

⍝ take a peek at the data
response.Data
<!DOCTYPE html><html><head><title>Page Title</title></head><body><h1>Requesting: /</h1><p><table ><tr><td>host</td><td>127.0.0.1</td></tr>

<tr><td>user-agent</td><td>Dyalog/Conga</td></tr>

<tr><td>accept</td><td>*/*</td></tr>

<tr><td>accept-encoding</td><td>gzip, deflate</td></tr>

</table></p></body></html>


I hope this helps!
/Brian
User avatar
Brian|Dyalog
 
Posts: 116
Joined: Thu Nov 26, 2009 4:02 pm
Location: West Henrietta, NY

Re: Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Tue Jan 08, 2019 4:22 pm

Thanks very much! Where in the example do you "override the onHtmlReq method" ?

I apologize that most of my APL skills date back to the early 1970s so "classes" and "namespaces" are like learning a second language as an adult.
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby Brian|Dyalog on Thu Jan 10, 2019 3:34 pm

Hi Tom,

Having learned APL in the 1970's as well, I can empathize with classes and namespaces seeming other-worldly, but, they are quite useful and well worth the time to learn a bit about.

The onHtmlReq method is in the DocHttpRequest class, which itself is derived from the HttpServerBase class, which is derived from the Conga.Connection class. (You can tell when a class is derived when you at the first line in the class definition - the base class is the name after the colon in the :Class statement.

So, HttpBaseServer has an overrideable onHtmlReq method that provides a stub with little functionality...
Code: Select all
    ∇ onHtmlReq
      :Access public overridable
      _←SendAnswer 0 ''('You are asking for ',Page)
    ∇

And DocHttpRequest has an overrideen onHtmlReq that replaces the functionality of HttpBaseServer's with something a bit more useful...
Code: Select all
    ∇ onHtmlReq;html;headers;hdr;e
      :Access public override
      html←'<!DOCTYPE html><html><head><title>Page Title</title></head><body><h1>Requesting: ',Page,'</h1><p>',(Table Headers),'</p></body></html>'
      headers←0 2⍴⍬
      headers⍪←'Server' 'ClassyDyalog'
      headers⍪←'Content-Type' 'text/html'
      hdr←(-⍴NL)↓⊃,/{⍺,': ',⍵,NL}/headers
      e←SendAnswer 0 hdr html
    ∇

In DocHttpRequest.onHtmlReq, we can see that we're composing the HTML response, defining a couple of headers, and then sending the response back to the client.

For your application, I would recommend you copy and rename the DocHttpRequest to an appropriate name and then modify onHtmlReq to meet your application's needs.

I hope this helps!

/Brian
User avatar
Brian|Dyalog
 
Posts: 116
Joined: Thu Nov 26, 2009 4:02 pm
Location: West Henrietta, NY

Re: Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Thu Jan 10, 2019 4:53 pm

Very clear now. Thanks!
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Mon Mar 11, 2019 11:00 pm

I have a workspace that does various communications in 5 simultaneous threads. (it operates on a Raspberry PI to collect information from a variety of websites and systems and intercommunicate between various home automation systems). In several places I use the HttpCommand.Get shortcut. I think but am not sure that this is the source of what seems to be hidden (trapped) errors. The workspace is working but often when I issue a ⎕DM to see whether there are any errors I get the result
⎕DM
VALUE ERROR HttpCmd[65] secure←{6::⍵ ⋄ ⍵∨0<⍴,certs}(lc(p-2)↑url)≡'https:' ∧
(the caret is to the right of the statement on my display)

Because execution does not stop I can't tell exactly where this is coming from.

I am not using secure communications. Is there an easy way to avoid this error or to diagnose the problem? In some way the error seems to be rendered irrelevant but I would rather prevent it from happening in the first place.

Perhaps I should use a Hold/EndHold control to prevent HttpCommand confusing itself with simultaneous calls? I am doing this with certain calls to prevent overlapping requests to a particular system where there a request is sent followed by a Conga Loop to receive the answer but have not protected requests to diverse information resources using HttpCommand in this way.

Thanks in advance for any advice!
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby tomgarwin on Tue Mar 12, 2019 12:17 am

I think I was able to discern the source of the error:

It appears that a few lines below the line where the error occurs there is this statement:

:If 0=⎕NC'certs' ⋄ certs←'' ⋄ :EndIf

copying this to precede the HttpCmd[65] statement where the error occurs seems to solve the problem in the active workspace. But obviously this won't protect against reloading the current version or loading an unfixed future version of HttpCommand

The HttpCommand version I am using appears to be 'HttpCommand' '2.1.19' '2018-12-04'
tomgarwin
 
Posts: 23
Joined: Sun Jul 23, 2017 11:37 am

Re: Best Way to send HTTP 200 OK code back to client

Postby AndyS|Dyalog on Tue Mar 12, 2019 1:47 pm

Hi Tom

⎕DM is set when an error occurs, and isn't changed until either a second error is generated, or you call ⎕SIGNAL 0 or )reset etc. So although the code traps the VALUE ERROR (because certs doesn't exist) ⎕DM/⎕EN are still updated to reflect this error.

You should use ⎕DMX rather than ⎕DM; values in the current instance of ⎕DMX effectively only last for the duration of the trap handling code. Not only that, but you've got 5 threads; ⎕DMX has thread scope, whereas ⎕DM/⎕EN have workspace scope. I also recommend, when developing code, to get into the habit of running d←⎕dmx as soon as the error is signalled and then look at what's in d .. too many times have I attempted to look at, for example, ⎕DMX.InternalLocation but mistyped it and promptly lost the valuable information that was in ⎕DMX.

As it is, Adam has just committed a change to HttpCommand so that the code now checks whether certs exists or not before trying to use the value. That will appear in any future update to Dyalog APL for the Raspberry Pi.
User avatar
AndyS|Dyalog
 
Posts: 257
Joined: Tue May 12, 2009 6:06 pm

Next

Return to MiServer

Who is online

Users browsing this forum: No registered users and 1 guest