www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Hello world/Web server task on RosettaCode fails

reply btiffin <btiffin gnu.org> writes:
Using gdc-11 and Seamonkey.  
https://rosettacode.org/wiki/Hello_world/Web_server#D does not 
compile.

```d
prompt$ gdc-11 helloServer.d
helloServer.d:12:29: error: cannot cast expression currSock = 
listener.accept() of type std.socket.Socket to bool
    12 |   while(cast(bool)(currSock = listener.accept())) {
       |                             ^
```

Then, tweaking the while loop to not cast but just run forever, 
`while (true) ...`, the code runs, but no data is shipped to 
browser.  Ctrl-U shows empty page after the accept and sendTo 
calls.

If this is the wrong place for this kind of info note, I'll 
gladly move to or redo the post in a more appropriate spot.

Have good, make well
Jul 16 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Friday, 16 July 2021 at 19:25:32 UTC, btiffin wrote:
 Using gdc-11 and Seamonkey.  
 https://rosettacode.org/wiki/Hello_world/Web_server#D does not 
 compile.
The `while` as you noted is wrong. The server also doesn't turn REUSEADDR on for the server socket, so this will be very annoying to test as you'll frequently get "address already in use" errors when you restart the server. The delimited string leads to your last problem: a blank space between the headers and the body of the response results in "\r\n \r\n" being sent rather than "\r\n\r\n", so the browser gives up on the invalid HTTP. This works if you're careful to not re-add any stray whitespace in the response: ```d import std.socket, std.array; ushort port = 8080; void main() { Socket listener = new TcpSocket; listener.bind(new InternetAddress(port)); listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1); listener.listen(10); Socket currSock; while (null !is (currSock = listener.accept())) { currSock.sendTo(replace(q"EOF HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 <html> <head><title>Hello, world!</title></head> <body>Hello, world!</body> </html> EOF", "\n", "\r\n")); currSock.close(); } } ``` Personally I'd prefer something more like: ```d import std.socket : Socket, TcpSocket, SocketOption, SocketOptionLevel, InternetAddress; import std.array : replace, array; import std.algorithm : map, joiner; import std.string : splitLines, strip; import std.conv : to; ushort port = 8080; // dfmt off static const greeting = q"EOF HTTP/1.1 200 OK Content-Type: text/html; charset=UTF-8 <html> <head><title>Hello, world!</title></head> <body>Hello, world!</body> </html> EOF" .splitLines .map!strip .joiner("\r\n") .to!string; // dfmt on void main() { import std.stdio : writefln; Socket listener = new TcpSocket; listener.bind(new InternetAddress(port)); listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, 1); listener.listen(10); writefln!"Listening on port %d."(port); while (true) { scope client = listener.accept; writefln!"Received connection from %s."(client.remoteAddress.toString); client.send(greeting); client.close; } } ``` But this *still violates HTTP* by not receiving the client's request, so it's still not a good answer for the task. A vibe hello world would make a lot more sense: https://github.com/vibe-d/vibe.d/blob/master/examples/http_server/source/app.d
 If this is the wrong place for this kind of info note, I'll 
 gladly move to or redo the post in a more appropriate spot.
You're in the right place.
Jul 16 2021
next sibling parent jfondren <julian.fondren gmail.com> writes:
On Friday, 16 July 2021 at 20:04:21 UTC, jfondren wrote:
 static const greeting = q"EOF
Or just `immutable greeting = ...`
Jul 16 2021
prev sibling parent reply btiffin <btiffin gnu.org> writes:
On Friday, 16 July 2021 at 20:04:21 UTC, jfondren wrote:
 On Friday, 16 July 2021 at 19:25:32 UTC, btiffin wrote:
 Using gdc-11 and Seamonkey.  
 https://rosettacode.org/wiki/Hello_world/Web_server#D does not 
 compile.
The `while` as you noted is wrong. The server also doesn't turn REUSEADDR on for the server socket, so this will be very annoying to test as you'll frequently get "address already in use" errors when you restart the server. The delimited string leads to your last problem: a blank space between the headers and the body of the response results in "\r\n \r\n" being sent rather than "\r\n\r\n", so the browser gives up on the invalid HTTP.
Ahh, thanks. The spaces. And turning on REUSEADDR made playing with the code a fair bit more fun. But, I mainly made the note to motivate a D aficionado to update and fix the Rosetta entry so that it at least compiles. Perhaps the whole *be bold* thing, and make the sources as idiomatic and correctly concise as D deserves. As a for instance, task description calls for Goodbye as the text in the solution.
 This works if you're careful to not re-add any stray whitespace 
 in the response:
...
 But this *still violates HTTP* by not receiving the client's 
 request, so it's still not a good answer for the task. A vibe 
 hello world would make a lot more sense:
 https://github.com/vibe-d/vibe.d/blob/master/examples/http_server/source/app.d

 If this is the wrong place for this kind of info note, I'll 
 gladly move to or redo the post in a more appropriate spot.
You're in the right place.
Cool. It's a nice place. :-) Cheers
Jul 16 2021
parent Brian Tiffin <btiffin gnu.org> writes:
On Saturday, 17 July 2021 at 04:13:53 UTC, btiffin wrote:
 On Friday, 16 July 2021 at 20:04:21 UTC, jfondren wrote:
 On Friday, 16 July 2021 at 19:25:32 UTC, btiffin wrote:
 Using gdc-11 and Seamonkey.  
 https://rosettacode.org/wiki/Hello_world/Web_server#D does 
 not compile.
The `while` as you noted is wrong. The server also doesn't turn REUSEADDR
...
 But, I mainly made the note to motivate a D aficionado to 
 update and fix the Rosetta entry so that it at least compiles.
Updated the entry. Not improved, just fixed the cast(bool) to !is null, so the solution compiles.
Jul 18 2021