[ANN] ZnReadEvalPrintDelegate

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

[ANN] ZnReadEvalPrintDelegate

Sven Van Caekenberghe-2
Hi,

Here is a little tool that might be useful to some you. For others it might be a nice example.

So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.

ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.

        ZnReadEvalPrintDelegate startInServerOn: 1701.

There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.

        ZnClient new
                url: 'http://localhost:1701/repl';
                contents: '42 factorial';
                post.

Here is an example terminal session (logged in to the server, not remote):

A GET on the service /repl gives some help text

$ curl http://localhost:1701/repl
# Pharo Smalltalk REPL. POST expressions to evaluate
# Here is one way (type ctrl-d to end input)
curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl

A POST with -d is good for short expressions

$ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
1405006117752879898543142606244511569936384000000000

For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.

$ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
{ (1 to: 10) sum. (1 to: 10) average }
{55. (11/2)}

There is error handling as well:

$ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
1 plus: 2
MessageNotUnderstood: SmallInteger>>plus:
SmallInteger(Object)>>doesNotUnderstand: #plus:
        Receiver: 1
        Arguments and temporary variables:
                aMessage: plus: 2
                exception: MessageNotUnderstood: SmallInteger>>plus:
                resumeValue: nil
        Receiver's instance variables:
1
UndefinedObject>>DoIt
Compiler>>evaluate:in:to:notifying:ifFail:logged:
Compiler>>evaluate:in:to:notifying:ifFail:
Compiler>>evaluate:in:to:
ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
BlockClosure>>on:do:
ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
String class(SequenceableCollection class)>>new:streamContents:

WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:

$ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl

All this in one class and a handful of methods.

Enjoy,

Sven

PS1: Part of Zinc HTTP Components, in the bleedingEdge version.

PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.

--
Sven Van Caekenberghe
Proudly supporting Pharo
http://pharo.org
http://association.pharo.org
http://consortium.pharo.org





Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Camillo Bruni-3
cool :)


On 2013-05-16, at 14:36, Sven Van Caekenberghe <[hidden email]> wrote:

> Hi,
>
> Here is a little tool that might be useful to some you. For others it might be a nice example.
>
> So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.
>
> ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.
>
> ZnReadEvalPrintDelegate startInServerOn: 1701.
>
> There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.
>
> ZnClient new
> url: 'http://localhost:1701/repl';
> contents: '42 factorial';
> post.
>
> Here is an example terminal session (logged in to the server, not remote):
>
> A GET on the service /repl gives some help text
>
> $ curl http://localhost:1701/repl
> # Pharo Smalltalk REPL. POST expressions to evaluate
> # Here is one way (type ctrl-d to end input)
> curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>
> A POST with -d is good for short expressions
>
> $ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
> 1405006117752879898543142606244511569936384000000000
>
> For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.
>
> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
> { (1 to: 10) sum. (1 to: 10) average }
> {55. (11/2)}
>
> There is error handling as well:
>
> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
> 1 plus: 2
> MessageNotUnderstood: SmallInteger>>plus:
> SmallInteger(Object)>>doesNotUnderstand: #plus:
> Receiver: 1
> Arguments and temporary variables:
> aMessage: plus: 2
> exception: MessageNotUnderstood: SmallInteger>>plus:
> resumeValue: nil
> Receiver's instance variables:
> 1
> UndefinedObject>>DoIt
> Compiler>>evaluate:in:to:notifying:ifFail:logged:
> Compiler>>evaluate:in:to:notifying:ifFail:
> Compiler>>evaluate:in:to:
> ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
> BlockClosure>>on:do:
> ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
> String class(SequenceableCollection class)>>new:streamContents:
>
> WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:
>
> $ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl
>
> All this in one class and a handful of methods.
>
> Enjoy,
>
> Sven
>
> PS1: Part of Zinc HTTP Components, in the bleedingEdge version.
>
> PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.
>
> --
> Sven Van Caekenberghe
> Proudly supporting Pharo
> http://pharo.org
> http://association.pharo.org
> http://consortium.pharo.org
>
>
>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Sven Van Caekenberghe-2

On 16 May 2013, at 14:41, Camillo Bruni <[hidden email]> wrote:

> cool :)

Thx, it is actually very simple, just a little hack.

I wanted to make it work like your zero-conf scripts

$ curl localhost:1701/repl | bash

But that does not seem possible (after a day of fruitless bash hacking ;-): bash already reads its script from stdin, hence the script itself cannot read his own input from stdin (or so it seems).

If you would happen to know how to do it …

> On 2013-05-16, at 14:36, Sven Van Caekenberghe <[hidden email]> wrote:
>
>> Hi,
>>
>> Here is a little tool that might be useful to some you. For others it might be a nice example.
>>
>> So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.
>>
>> ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.
>>
>> ZnReadEvalPrintDelegate startInServerOn: 1701.
>>
>> There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.
>>
>> ZnClient new
>> url: 'http://localhost:1701/repl';
>> contents: '42 factorial';
>> post.
>>
>> Here is an example terminal session (logged in to the server, not remote):
>>
>> A GET on the service /repl gives some help text
>>
>> $ curl http://localhost:1701/repl
>> # Pharo Smalltalk REPL. POST expressions to evaluate
>> # Here is one way (type ctrl-d to end input)
>> curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>>
>> A POST with -d is good for short expressions
>>
>> $ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
>> 1405006117752879898543142606244511569936384000000000
>>
>> For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.
>>
>> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>> { (1 to: 10) sum. (1 to: 10) average }
>> {55. (11/2)}
>>
>> There is error handling as well:
>>
>> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>> 1 plus: 2
>> MessageNotUnderstood: SmallInteger>>plus:
>> SmallInteger(Object)>>doesNotUnderstand: #plus:
>> Receiver: 1
>> Arguments and temporary variables:
>> aMessage: plus: 2
>> exception: MessageNotUnderstood: SmallInteger>>plus:
>> resumeValue: nil
>> Receiver's instance variables:
>> 1
>> UndefinedObject>>DoIt
>> Compiler>>evaluate:in:to:notifying:ifFail:logged:
>> Compiler>>evaluate:in:to:notifying:ifFail:
>> Compiler>>evaluate:in:to:
>> ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
>> BlockClosure>>on:do:
>> ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
>> String class(SequenceableCollection class)>>new:streamContents:
>>
>> WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:
>>
>> $ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl
>>
>> All this in one class and a handful of methods.
>>
>> Enjoy,
>>
>> Sven
>>
>> PS1: Part of Zinc HTTP Components, in the bleedingEdge version.
>>
>> PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.
>>
>> --
>> Sven Van Caekenberghe
>> Proudly supporting Pharo
>> http://pharo.org
>> http://association.pharo.org
>> http://consortium.pharo.org
>>
>>
>>
>>
>>
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Esteban A. Maringolo
In reply to this post by Camillo Bruni-3
Really cool.

Esteban A. Maringolo


2013/5/16 Camillo Bruni <[hidden email]>
cool :)


On 2013-05-16, at 14:36, Sven Van Caekenberghe <[hidden email]> wrote:

> Hi,
>
> Here is a little tool that might be useful to some you. For others it might be a nice example.
>
> So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.
>
> ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.
>
>       ZnReadEvalPrintDelegate startInServerOn: 1701.
>
> There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.
>
>       ZnClient new
>               url: 'http://localhost:1701/repl';
>               contents: '42 factorial';
>               post.
>
> Here is an example terminal session (logged in to the server, not remote):
>
> A GET on the service /repl gives some help text
>
> $ curl http://localhost:1701/repl
> # Pharo Smalltalk REPL. POST expressions to evaluate
> # Here is one way (type ctrl-d to end input)
> curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>
> A POST with -d is good for short expressions
>
> $ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
> 1405006117752879898543142606244511569936384000000000
>
> For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.
>
> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
> { (1 to: 10) sum. (1 to: 10) average }
> {55. (11/2)}
>
> There is error handling as well:
>
> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
> 1 plus: 2
> MessageNotUnderstood: SmallInteger>>plus:
> SmallInteger(Object)>>doesNotUnderstand: #plus:
>       Receiver: 1
>       Arguments and temporary variables:
>               aMessage:       plus: 2
>               exception:      MessageNotUnderstood: SmallInteger>>plus:
>               resumeValue:    nil
>       Receiver's instance variables:
> 1
> UndefinedObject>>DoIt
> Compiler>>evaluate:in:to:notifying:ifFail:logged:
> Compiler>>evaluate:in:to:notifying:ifFail:
> Compiler>>evaluate:in:to:
> ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
> BlockClosure>>on:do:
> ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
> String class(SequenceableCollection class)>>new:streamContents:
>
> WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:
>
> $ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl
>
> All this in one class and a handful of methods.
>
> Enjoy,
>
> Sven
>
> PS1: Part of Zinc HTTP Components, in the bleedingEdge version.
>
> PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.
>
> --
> Sven Van Caekenberghe
> Proudly supporting Pharo
> http://pharo.org
> http://association.pharo.org
> http://consortium.pharo.org
>
>
>
>
>



Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Ben Coman
In reply to this post by Sven Van Caekenberghe-2
Very cool.  btw, does the Zinc HTTPS handle client-certificates?  That
might be reasonably secure if a private tunnel to the box is not available.

cheers -ben

Sven Van Caekenberghe wrote:

> Hi,
>
> Here is a little tool that might be useful to some you. For others it might be a nice example.
>
> So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.
>
> ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.
>
> ZnReadEvalPrintDelegate startInServerOn: 1701.
>
> There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.
>
> ZnClient new
> url: 'http://localhost:1701/repl';
> contents: '42 factorial';
> post.
>
> Here is an example terminal session (logged in to the server, not remote):
>
> A GET on the service /repl gives some help text
>
> $ curl http://localhost:1701/repl
> # Pharo Smalltalk REPL. POST expressions to evaluate
> # Here is one way (type ctrl-d to end input)
> curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>
> A POST with -d is good for short expressions
>
> $ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
> 1405006117752879898543142606244511569936384000000000
>
> For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.
>
> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
> { (1 to: 10) sum. (1 to: 10) average }
> {55. (11/2)}
>
> There is error handling as well:
>
> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
> 1 plus: 2
> MessageNotUnderstood: SmallInteger>>plus:
> SmallInteger(Object)>>doesNotUnderstand: #plus:
> Receiver: 1
> Arguments and temporary variables:
> aMessage: plus: 2
> exception: MessageNotUnderstood: SmallInteger>>plus:
> resumeValue: nil
> Receiver's instance variables:
> 1
> UndefinedObject>>DoIt
> Compiler>>evaluate:in:to:notifying:ifFail:logged:
> Compiler>>evaluate:in:to:notifying:ifFail:
> Compiler>>evaluate:in:to:
> ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
> BlockClosure>>on:do:
> ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
> String class(SequenceableCollection class)>>new:streamContents:
>
> WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:
>
> $ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl
>
> All this in one class and a handful of methods.
>
> Enjoy,
>
> Sven
>
> PS1: Part of Zinc HTTP Components, in the bleedingEdge version.
>
> PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.
>
> --
> Sven Van Caekenberghe
> Proudly supporting Pharo
> http://pharo.org
> http://association.pharo.org
> http://consortium.pharo.org
>
>
>
>
>
>
>  


Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Sven Van Caekenberghe-2
Ben,

On 16 May 2013, at 20:30, [hidden email] wrote:

> Very cool.  btw, does the Zinc HTTPS handle client-certificates?  

Certificate management in Zodiac TLS/SSL is weak and platform dependent: basically, the primitives are incompletely implemented. This is not an easy subject.

> That might be reasonably secure if a private tunnel to the box is not available.

I can't imagine working with a server unless I can ssh into it, hence

        ssh -L1701:localhost:1701 myserver.com

would be enough to establish the tunnel. But once you are on the host, you can do the curl requests there of course.

As for remote access, Basic Authentication over HTTPS seems sufficient to me, though it isn't perfect. We use this in production for remote web service APIs. Here is how you could set it up:

(ZnSecureServer on: 1443)
        certificate: '/home/sven/ssl/key-cert.pem';
        delegate: ZnReadEvalPrintDelegate new;
        authenticator: (ZnBasicAuthenticator username: '[hidden email]' password: 'Sm@lltalk');
        start.

Alternatively, an Apache or Nginx proxy with client certificates would do the trick as well.

Sven

> cheers -ben
>
> Sven Van Caekenberghe wrote:
>> Hi,
>>
>> Here is a little tool that might be useful to some you. For others it might be a nice example.
>>
>> So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.
>>
>> ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.
>>
>> ZnReadEvalPrintDelegate startInServerOn: 1701.
>>
>> There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.
>>
>> ZnClient new
>> url: 'http://localhost:1701/repl';
>> contents: '42 factorial';
>> post.
>>
>> Here is an example terminal session (logged in to the server, not remote):
>>
>> A GET on the service /repl gives some help text
>>
>> $ curl http://localhost:1701/repl
>> # Pharo Smalltalk REPL. POST expressions to evaluate
>> # Here is one way (type ctrl-d to end input)
>> curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>>
>> A POST with -d is good for short expressions
>>
>> $ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
>> 1405006117752879898543142606244511569936384000000000
>>
>> For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.
>>
>> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>> { (1 to: 10) sum. (1 to: 10) average }
>> {55. (11/2)}
>>
>> There is error handling as well:
>>
>> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>> 1 plus: 2
>> MessageNotUnderstood: SmallInteger>>plus:
>> SmallInteger(Object)>>doesNotUnderstand: #plus:
>> Receiver: 1
>> Arguments and temporary variables: aMessage: plus: 2
>> exception: MessageNotUnderstood: SmallInteger>>plus:
>> resumeValue: nil
>> Receiver's instance variables: 1
>> UndefinedObject>>DoIt
>> Compiler>>evaluate:in:to:notifying:ifFail:logged:
>> Compiler>>evaluate:in:to:notifying:ifFail:
>> Compiler>>evaluate:in:to:
>> ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
>> BlockClosure>>on:do:
>> ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
>> String class(SequenceableCollection class)>>new:streamContents:
>>
>> WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:
>>
>> $ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl
>>
>> All this in one class and a handful of methods.
>>
>> Enjoy,
>>
>> Sven
>>
>> PS1: Part of Zinc HTTP Components, in the bleedingEdge version.
>>
>> PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.
>>
>> --
>> Sven Van Caekenberghe
>> Proudly supporting Pharo
>> http://pharo.org
>> http://association.pharo.org
>> http://consortium.pharo.org
>>
>>
>>
>>
>>
>>
>>  
>
>


Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Ben Coman
Thanks for that detailed reply.  Not using server side Smalltalk right now, but it will be useful to me in the near future.

Sven Van Caekenberghe wrote:
Ben,

On 16 May 2013, at 20:30, [hidden email] wrote:

  
Very cool.  btw, does the Zinc HTTPS handle client-certificates?  
    

Certificate management in Zodiac TLS/SSL is weak and platform dependent: basically, the primitives are incompletely implemented. This is not an easy subject.

  
That might be reasonably secure if a private tunnel to the box is not available.
    

I can't imagine working with a server unless I can ssh into it, hence

	ssh -L1701:localhost:1701 myserver.com

would be enough to establish the tunnel. But once you are on the host, you can do the curl requests there of course.

As for remote access, Basic Authentication over HTTPS seems sufficient to me, though it isn't perfect. We use this in production for remote web service APIs. Here is how you could set it up:

(ZnSecureServer on: 1443)
	certificate: '/home/sven/ssl/key-cert.pem';
	delegate: ZnReadEvalPrintDelegate new;
	authenticator: (ZnBasicAuthenticator username: '[hidden email]' password: 'Sm@lltalk');
	start.

Alternatively, an Apache or Nginx proxy with client certificates would do the trick as well.

Sven 

  
cheers -ben

Sven Van Caekenberghe wrote:
    
Hi,

Here is a little tool that might be useful to some you. For others it might be a nice example.

So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.

ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.

	ZnReadEvalPrintDelegate startInServerOn: 1701.

There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.	

	ZnClient new
		url: 'http://localhost:1701/repl';
		contents: '42 factorial';
		post.

Here is an example terminal session (logged in to the server, not remote):

A GET on the service /repl gives some help text

$ curl http://localhost:1701/repl
# Pharo Smalltalk REPL. POST expressions to evaluate
# Here is one way (type ctrl-d to end input)
curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl

A POST with -d is good for short expressions

$ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
1405006117752879898543142606244511569936384000000000

For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.

$ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
{ (1 to: 10) sum. (1 to: 10) average }
{55. (11/2)}

There is error handling as well:

$ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
1 plus: 2
MessageNotUnderstood: SmallInteger>>plus:
SmallInteger(Object)>>doesNotUnderstand: #plus:
	Receiver: 1
	Arguments and temporary variables: 		aMessage: 	plus: 2
		exception: 	MessageNotUnderstood: SmallInteger>>plus:
		resumeValue: 	nil
	Receiver's instance variables: 1
UndefinedObject>>DoIt
Compiler>>evaluate:in:to:notifying:ifFail:logged:
Compiler>>evaluate:in:to:notifying:ifFail:
Compiler>>evaluate:in:to:
ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
BlockClosure>>on:do:
ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
String class(SequenceableCollection class)>>new:streamContents:

WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:

$ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl

All this in one class and a handful of methods.

Enjoy,

Sven

PS1: Part of Zinc HTTP Components, in the bleedingEdge version.

PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.

--
Sven Van Caekenberghe
Proudly supporting Pharo
http://pharo.org
http://association.pharo.org
http://consortium.pharo.org






 
      
    



  

Reply | Threaded
Open this post in threaded view
|

Re: [ANN] ZnReadEvalPrintDelegate

Igor Stasenko
In reply to this post by Sven Van Caekenberghe-2
On 16 May 2013 15:05, Sven Van Caekenberghe <[hidden email]> wrote:

>
> On 16 May 2013, at 14:41, Camillo Bruni <[hidden email]> wrote:
>
>> cool :)
>
> Thx, it is actually very simple, just a little hack.
>
> I wanted to make it work like your zero-conf scripts
>
> $ curl localhost:1701/repl | bash
>
> But that does not seem possible (after a day of fruitless bash hacking ;-): bash already reads its script from stdin, hence the script itself cannot read his own input from stdin (or so it seems).
>
> If you would happen to know how to do it …
>
you know you can always add one more pipe, do you?

<whatever gives some output to> | <this guy who consumes it and gives
to> | <another guy which consumes it and outputs the result>

:)

>> On 2013-05-16, at 14:36, Sven Van Caekenberghe <[hidden email]> wrote:
>>
>>> Hi,
>>>
>>> Here is a little tool that might be useful to some you. For others it might be a nice example.
>>>
>>> So you have your shiny Pharo server application running in the cloud. When something goes wrong, most of the time you will just restart, manually or automatically. But sometimes you wish you could interact with a running headless server image. Problem is, you can't out of the box.
>>>
>>> ZnReadEvalPrintDelegate is a simple tool that exports a REPL Web Service. Much like the emergency evaluator. Primitive but better than nothing. Install it on a port of your choice, running in a independent Zn HTTP server, bound to localhost only.
>>>
>>>      ZnReadEvalPrintDelegate startInServerOn: 1701.
>>>
>>> There is only one API method: POST a plain/text Smalltalk expression to evaluate, get the result back.
>>>
>>>      ZnClient new
>>>              url: 'http://localhost:1701/repl';
>>>              contents: '42 factorial';
>>>              post.
>>>
>>> Here is an example terminal session (logged in to the server, not remote):
>>>
>>> A GET on the service /repl gives some help text
>>>
>>> $ curl http://localhost:1701/repl
>>> # Pharo Smalltalk REPL. POST expressions to evaluate
>>> # Here is one way (type ctrl-d to end input)
>>> curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>>>
>>> A POST with -d is good for short expressions
>>>
>>> $ curl -X POST -H'Content-Type:text/plain' -d '42 factorial' http://localhost:1701/repl
>>> 1405006117752879898543142606244511569936384000000000
>>>
>>> For longer or multi line expressions you can read input from stdin and end with ctrl-d (copy the expression returned by the GET). Or you could send text files.
>>>
>>> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>>> { (1 to: 10) sum. (1 to: 10) average }
>>> {55. (11/2)}
>>>
>>> There is error handling as well:
>>>
>>> $ curl -X POST -H'Content-Type:text/plain' --data-binary @- http://localhost:1701/repl
>>> 1 plus: 2
>>> MessageNotUnderstood: SmallInteger>>plus:
>>> SmallInteger(Object)>>doesNotUnderstand: #plus:
>>>      Receiver: 1
>>>      Arguments and temporary variables:
>>>              aMessage:       plus: 2
>>>              exception:      MessageNotUnderstood: SmallInteger>>plus:
>>>              resumeValue:    nil
>>>      Receiver's instance variables:
>>> 1
>>> UndefinedObject>>DoIt
>>> Compiler>>evaluate:in:to:notifying:ifFail:logged:
>>> Compiler>>evaluate:in:to:notifying:ifFail:
>>> Compiler>>evaluate:in:to:
>>> ZnReadEvalPrintDelegate>>evaluate: in Block: [| result |...
>>> BlockClosure>>on:do:
>>> ZnReadEvalPrintDelegate>>evaluate: in Block: [:out | [| result |...
>>> String class(SequenceableCollection class)>>new:streamContents:
>>>
>>> WARNING: never open this service beyond your local network ! This service gives you absolute control over and access to everything in your image. For example, the following will kill your image:
>>>
>>> $ curl -X POST -H'Content-Type:text/plain' -d 'Smalltalk quitPrimitive' http://localhost:1701/repl
>>>
>>> All this in one class and a handful of methods.
>>>
>>> Enjoy,
>>>
>>> Sven
>>>
>>> PS1: Part of Zinc HTTP Components, in the bleedingEdge version.
>>>
>>> PS2: Of course, basic authentication or HTTPS can be added through simple Zn configuration.
>>>
>>> --
>>> Sven Van Caekenberghe
>>> Proudly supporting Pharo
>>> http://pharo.org
>>> http://association.pharo.org
>>> http://consortium.pharo.org
>>>
>>>
>>>
>>>
>>>
>>
>>
>
>



--
Best regards,
Igor Stasenko.