Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http_pengine_send does not accept application/json #15

Open
Anniepoo opened this issue May 1, 2016 · 11 comments
Open

http_pengine_send does not accept application/json #15

Anniepoo opened this issue May 1, 2016 · 11 comments
Labels

Comments

@Anniepoo
Copy link
Member

Anniepoo commented May 1, 2016

http_pengine_create accepts application/json,

but POST requests to http_pengine_send only accept application/x-www-form-urlencoded

=8cO <-- Annie discovering this while implementing java client

@JanWielemaker
Copy link
Member

No. It accepts application/json, but you must tell it you are sending that using the Content-type in the POST header.

@Anniepoo
Copy link
Member Author

Anniepoo commented May 1, 2016

TRIGGER WARNING - Java below!

void doAsk(Query query, String ask) throws PengineNotReadyException {
    state.must_be_in(PSt.IDLE, PSt.ASK);

    URL url = po.getActualURL("send");
    StringBuffer response;

// TODO can we abstract this?

    try {
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        // above should get us an HttpsURLConnection if it's https://...

        //add request header
        con.setRequestMethod("POST");
        con.setRequestProperty("User-Agent", "JavaPengine");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
        con.setRequestProperty("Content-type", "application/json");

        String urlParameters = po.getRequestBodyAsk(this.getID(), ask);

        // Send post request
        con.setDoOutput(true);
        DataOutputStream wr = new DataOutputStream(con.getOutputStream());
        try {
            wr.writeBytes(urlParameters);
            wr.flush();
        } finally {
            wr.close();
        }

        int responseCode = con.getResponseCode();
        if(responseCode < 200 || responseCode > 299) {
            throw new PengineNotAvailableException("bad response code (if 500, perhaps query was invalid? Or query threw Prolog exception?)" + Integer.toString(responseCode));
        }

        BufferedReader in = new BufferedReader(
                new InputStreamReader(con.getInputStream()));
        String inputLine;
        response = new StringBuffer();
        try {
            while ((inputLine = in.readLine()) != null) {
                response.append(inputLine);
            }
        } finally {
            in.close();
        }

        JsonReaderFactory jrf = Json.createReaderFactory(null);
        JsonReader jr = jrf.createReader(new StringReader(response.toString()));
        JsonObject respObject = jr.readObject();

        JsonString eventjson = (JsonString)respObject.get("event");
        String evtstr = eventjson.getString();

        // TODO need to use this much of it to probe

        if(respObject.containsKey("answer")) {
            handleAnswer(respObject.getJsonObject("answer"));
        }

    } catch (IOException e) {
        state.destroy();
        throw new PengineNotAvailableException(e.toString());
    } catch(SyntaxErrorException e) {
        state.destroy();
        throw new PengineNotAvailableException(e.getMessage());
    }

}

@Anniepoo
Copy link
Member Author

Anniepoo commented May 1, 2016

/pengines/create accepts but /pengines/send does not.

On the Java side I'm adding Accept: application/json and Content-Type: application/json headers

I assumed this was me, of course, at first, but the code's pretty clear on the server side. I stepped into it.

http handler calls http_pengine_send
first clause fails.

Second clause calls http_parameters, which is eventually going to call http_parms which calls form_data_content_type which in turn needs application/x-www-form-urlencoded

http_pengine_create handles this differently
http_pengine_create's 2nd clause does this

memberchk(content_type(CT), Request),
sub_atom(CT, 0, _, _, 'application/json'), !,
http_read_json_dict(Request, Dict),

and is handled correctly.

The code I'm using is essentially copy/paste from my create method.

Java involves much typing. 8cO

@JanWielemaker
Copy link
Member

True. /pengine/send expects a Prolog event. Might not be a great id. See the web/js/pengines.js
JavaScript client:

Pengine.prototype.send = function(event) {
  var pengine = this;

  $.ajax({ type: "POST",
       url: pengine.options.server +
        '/send?format=' + this.options.format +
        '&id=' + this.id,
       data: event + " .\n",
       contentType: "application/x-prolog; charset=UTF-8",
       success: function(obj) {
         pengine.process_response(obj);
       },
       error: function(jqXHR, textStatus, errorThrown) {
         pengine.error(jqXHR, textStatus, errorThrown);
       }
         });
};

The JavaScript client is probably the best documentation :) One route might be for you to complete the Java client, and before you start other ones, evaluate the oddities and possibly fix them.

@Anniepoo
Copy link
Member Author

Anniepoo commented May 1, 2016

OK - thanks for advice about JS client. I haven't looked at it - I've been following the main and Pengines sites and tracing through the Prolog implementation.

Are query strings allowed with POST ? RFC7231 is unclear on the subject, but I suspect it's buried somewhere. Obviously it's common to pass in body because that's what web forms do.

Anyway, I'll change JavaPengines to do this, and submit a fix that lets it use JSON.

@Anniepoo
Copy link
Member Author

Anniepoo commented May 4, 2016

And it won't respond with JSON either, even if the accept header is present it responds with raw Prolog.

@JanWielemaker
Copy link
Member

Again, see pengines.js:

  $.ajax({ type: "POST",
       url: pengine.options.server +
        '/send?format=' + this.options.format +
        '&id=' + this.id,

I.e, it sends a `format' parameter. Not sure this is a good idea. Some of this is history :(
Do you keep a record of oddities?

@Anniepoo
Copy link
Member Author

Anniepoo commented May 4, 2016

Ah! Thought that was format TO server
thanks.
Not sure what's an oddity, though the API seems a bit jumbled.

@wouterbeek
Copy link

@Anniepoo Is there still a remaining issue here or can this be closed?

@Anniepoo
Copy link
Member Author

Anniepoo commented May 7, 2016

leave open - its still true. having a workaround isnt a fix

@Anniepoo
Copy link
Member Author

Anniepoo commented May 7, 2016

i expect to fix in next week or so

@wouterbeek wouterbeek added the bug label May 7, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants