Using SimpleHttpFileServer


(Gérald Fauvelle) #1

Hello,

I’m running some unit tests on Android, and I have to run an http server locally to get images from it during my tests. Until now, I’m using a python script that run the SimpleHttpServer of python, then call Gradle, then kill the server at the end.

I’ve found that there is a SimpleHttpFileServer that could be used in Gradle.
But I can’t make it work. I found absolutely nothing about usage of this
class, except the doc here :

https://gradle.org/docs/current/javadoc/org/gradle/plugins/javascript/envjs/http/simple/SimpleHttpFileServer.html

that doesn’t say much. What is a Stoppable for instance? No doc about it.

When I try to use it, I have this error :
Could not find matching constructor for:
org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServer

Anyone here has played with that? Or do you see any other way to do it? Another idea was to run the python server from Gradle, then kill it at the end, probably using task.finalizedBy, but I didn’t success either.

Any help on any of those methods would be appreciated.

Thanks,

Gérald


(Mark Vieira) #2

You’ll want to use the SimpleHttpFileServerFactory to create instances of one of these. And yes, using finalizedBy to kill the server after running your tests is one way of doing things. Alternatively you could do the server startup/shutdown in your test code.


(Gérald Fauvelle) #3

Hi Mark,

Thanks, I’ll try that.
For your last remark, maybe I didn’t explained well, but my test code runs on an Android device, the HTTPserver is launched on a Linux or Windows desktop, and Android device communicate with that HTTP server, so I don’t think I can do what you describe.


(Mark Vieira) #4

Yes, if you are doing something like :connectedCheck then you’ll want to launch and shutdown the server from the Gradle build script.


(Gérald Fauvelle) #5

Yes, that’s exactly what I want to do.
I’ve tried with these tasks, I think I’m not far from having it work :smile:

task prepareFiles {
    println 'Preparing files'
    ant.importBuild '../../ant-copy.xml'
}

task pythonServer(type: ExecWait) {
    command 'python -m SimpleHTTPServer 8001'
    directory '../..'
    ready 'Serving'
}

task adbConnect(type: Exec, dependsOn: [prepareFiles, pythonServer]) {
   commandLine 'adb', 'connect', '192.168.200.92'
}

class ExecWait extends DefaultTask
{
    String command
    String ready
    String directory
    static Process process

    def doLast() {
        println 'dolast'
    }

    @TaskAction
    def spawnProcess()
    {
        //return // GF : spawnProcess works, but can't find a way to stop it for now

        println 'Starting server'
        File root = new File('../..')
        int port = 8001
        HttpFileServer server = SimpleHttpFileServerFactory.start(root, (int)port)

        println "Server started in directory "+server.getContentRoot()
    }
}

But I have an error :

  • Where:
    Build file ‘D:\src\64bits\products\TestReco.nrt\QAFeatJ\build.gradle’ line: 55

  • What went wrong:
    Execution failed for task ‘:pythonServer’.

No signature of method: static org.gradle.plugins.javascript.envjs.http.simple.SimpleHttpFileServerFactory.start() is applicable for argument types: (java.io.File, java.lang.Integer) values: […, 8001]
Possible solutions: start(java.io.File, int), wait(), wait(long, int), every(), any(), iterator()

Line 55 is where I call the SimpleHttpFileServerFactory. I give an int, why does it say it’s an java.lang.Integer ?


(Gérald Fauvelle) #6

Hmm, using it this way is better, I still don’t get the error message I had previously though :

SimpleHttpFileServerFactory factory = new SimpleHttpFileServerFactory()
HttpFileServer server = factory.start(root, port)

So now server is started, but I can browse anything, it doesn’t answer, it just binds the port I’m giving him.
Is there a real example of using HttpFileServer that is really working?


(Mark Vieira) #7

It’s just doing autoboxing. The error is a result of the fact that start() isn’t a static method so you need to create an instance of SimpleHttpFileServerFactory to call it.

I’m not sure I understand. Is the server not answering to requests? Given a file called ‘foo.jpg’ in the root dir, you should be able to browse to http://localhost:8001/foo.jpg.


(Gérald Fauvelle) #8

So it works, I can access the file with Firefox. But my lib java, using HttpURLConnection, I receive a EOFException. I’ll search a bit more on that.

Edit:
I just use :

HttpURLConnection httpConn = (HttpURLConnection) url.openConnection();
responseCode = httpConn.getResponseCode();

getResponseCode throw a EOFException when I try to connect to the http server launched by Gradle. I have no problem with http server from python or Apache. Is there a known problem with Gradle http server?


(Mark Vieira) #9

Not that I’m aware of. However, we are using a relatively old version of simpleframework for this.


(Laksh Gupta) #10

I read the discussion and am trying to implement a similar functionality, where Gradle starts a file server on the localhost before running a task (dependsOn) and then stops the server after the task finishes (finalizedBy). The problem I am facing is that calling stop on the HttpFileServer does not stop the port from listening. Because of which I get “address already in use” error when I run the task the second time. Below is the code I am using to implement the functionality.

   def httpFileServer = null
    task startHttpFileServer {
        doFirst{
            println 'Starting http file server'
            File root = new File("${buildDir}/stage")
            int port = 8530
            def factory = new SimpleHttpFileServerFactory()
            httpFileServer = factory.start(root, port)
            println "HTTP file Server started in directory " + httpFileServer.getContentRoot()
        }
    }


    task stopHttpFileServer {
    doLast{
        if (httpFileServer != null) {
            println 'Stopping Server..'
            httpFileServer.stop()
        }
    }
}

I am using Gradle 3.1 on SLES 12. Is this the expected behavior?