Open Anniepoo opened 8 years ago
No. It accepts application/json
, but you must tell it you are sending that using the Content-type
in the POST
header.
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());
}
}
/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
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.
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.
And it won't respond with JSON either, even if the accept header is present it responds with raw Prolog.
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?
Ah! Thought that was format TO server
thanks.
Not sure what's an oddity, though the API seems a bit jumbled.
@Anniepoo Is there still a remaining issue here or can this be closed?
leave open - its still true. having a workaround isnt a fix
i expect to fix in next week or so
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