Voor school ben ik bezig met het schrijven van een data API in Java. Middels simpele HTTP GET en POST requests kunnen JSON objecten worden opgehaald en weggeschreven worden. Gisteren avond was ik zo goed als klaar, alles zoals op papier uit geprogrammeerd en het werkt allemaal naar behoren. Er is echter één klein onderdeel waar ik niet uit komt, en wel een zeer belangrijk klein onderdeel, de POST data (dat de JSON string die geschreven moet worden bevat, niets anders) moet doorgegeven worden aan de handler van de request. De headers netjes uitlezen, etc gaat allemaal OK. Echter krijg ik dit niet voor elkaar. Hieronder de basis van de code die de headers uitleest en vervolgens gaat bepalen wat er moet gebeuren met het verzoek (dat werkt dus verder allemaal, alleen moet ik die JSON string nog tevoorschijn zien te toveren):
Zoals ik al zei, de headers komen netjes tevoorschijn. Ik veronderstelde eerst (heel dom natuurlijk), dat de POST data bij de request headers zouden zitten. Natuurlijk niet, dat is de body. Met de weinige kennis die ik van HTTP requests heb (ik zeg dit met nadruk omdat ik het globale plaatje natuurlijk snap, maar de fijnigheden weet ik er ook niet van), zou ik denken dat de headers eerst komen, elke header eindigt met een linebreak. Headers klaar -> empty line. Daarna zou de POST data als url encoded string moeten komen.
Blijkbaar niet. inFromClient.reader() geeft na de laatste header al aan dat het inkomende verzoek compleet binnen is. Ik ben gisteren meer dan twee uur bezig geweest om hier iets op te vinden, niet gelukt, daarom ben ik nou hier. Tot nu toe heb ik, zowel in de docs van alle betrokken klassen nog niks gevonden waar uit blijkt dat er bijv. uit inFromClient of connectedClient.getInputStream() ook maar enige andere vorm van informatie te trekken die de client mee stuurt. Ook kan ik geen vergelijkbare problemen op StackOverflow vinden (of ergens anders), laat staan voorbeelden die op een vergelijkbare manier omgaan met POST data (dus dan heb ik het niet over multipart data, het is altijd een string en is dat dus niet nodig.
Mijn projectgroep komt er ook niet uit, ze hebben mee gekeken, maar we zijn allemaal vrijwel ten einde raad. In eerste instantie heb ik nog aan m'n klasse getwijfeld die de requests doet naar de server, ik wist namelijk niet zeker of de POST data wel wordt meegestuurd. Daarom heb ik het naar een PHP script doorgestuurd en de POST data uitgelezen, allemaal in orde, request is gewoon OK. Ik heb het eveneens getest met een simpel HTML formulier dat handmatig een verzoek kan sturen. Nog krijg ik op geen enkele manier door wat er mee wordt gestuurd. Ten einde raad. Maar goed, volgens mij ben ik gewoon gek en zie ik iets over het hoofd. Er zullen vast mensen hier rondlopen die net weten hoe het wél moet. Iemand?
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| this.inFromClient = new BufferedReader(new InputStreamReader(this.connectedClient.getInputStream())); this.outToClient = new DataOutputStream(this.connectedClient.getOutputStream()); String requestString = this.inFromClient.readLine(); String headerLine = requestString; StringTokenizer tokenizer = new StringTokenizer(headerLine); String httpMethod = tokenizer.nextToken(); String httpQueryString = URLDecoder.decode(tokenizer.nextToken()); while (this.inFromClient.ready()) { System.out.println(requestString); requestString = this.inFromClient.readLine(); } // httpMethod en httpQueryString verwerken |
Zoals ik al zei, de headers komen netjes tevoorschijn. Ik veronderstelde eerst (heel dom natuurlijk), dat de POST data bij de request headers zouden zitten. Natuurlijk niet, dat is de body. Met de weinige kennis die ik van HTTP requests heb (ik zeg dit met nadruk omdat ik het globale plaatje natuurlijk snap, maar de fijnigheden weet ik er ook niet van), zou ik denken dat de headers eerst komen, elke header eindigt met een linebreak. Headers klaar -> empty line. Daarna zou de POST data als url encoded string moeten komen.
Blijkbaar niet. inFromClient.reader() geeft na de laatste header al aan dat het inkomende verzoek compleet binnen is. Ik ben gisteren meer dan twee uur bezig geweest om hier iets op te vinden, niet gelukt, daarom ben ik nou hier. Tot nu toe heb ik, zowel in de docs van alle betrokken klassen nog niks gevonden waar uit blijkt dat er bijv. uit inFromClient of connectedClient.getInputStream() ook maar enige andere vorm van informatie te trekken die de client mee stuurt. Ook kan ik geen vergelijkbare problemen op StackOverflow vinden (of ergens anders), laat staan voorbeelden die op een vergelijkbare manier omgaan met POST data (dus dan heb ik het niet over multipart data, het is altijd een string en is dat dus niet nodig.
Mijn projectgroep komt er ook niet uit, ze hebben mee gekeken, maar we zijn allemaal vrijwel ten einde raad. In eerste instantie heb ik nog aan m'n klasse getwijfeld die de requests doet naar de server, ik wist namelijk niet zeker of de POST data wel wordt meegestuurd. Daarom heb ik het naar een PHP script doorgestuurd en de POST data uitgelezen, allemaal in orde, request is gewoon OK. Ik heb het eveneens getest met een simpel HTML formulier dat handmatig een verzoek kan sturen. Nog krijg ik op geen enkele manier door wat er mee wordt gestuurd. Ten einde raad. Maar goed, volgens mij ben ik gewoon gek en zie ik iets over het hoofd. Er zullen vast mensen hier rondlopen die net weten hoe het wél moet. Iemand?
offtopic:
De API is puur voor opslag van (relationele) data in de vorm van objecten. Dit mag volgens de projectspecificaties niet gebeuren middels een RDMS en moet in de vorm van FileIO. Dit geheel moet ook nog eens gedeeld worden met andere deelsystemen. De meeste projectgroepen kiezen er voor om gewoon serialized object op Dropbox te pleuren, echter vond ik dit idee toch net een tikje beter. Bovendien vind ik het zeer interessant om (na jaren simpelweg Apache + PHP gebruikt te hebben) zelf een 'webserver' te implementeren.
De API is puur voor opslag van (relationele) data in de vorm van objecten. Dit mag volgens de projectspecificaties niet gebeuren middels een RDMS en moet in de vorm van FileIO. Dit geheel moet ook nog eens gedeeld worden met andere deelsystemen. De meeste projectgroepen kiezen er voor om gewoon serialized object op Dropbox te pleuren, echter vond ik dit idee toch net een tikje beter. Bovendien vind ik het zeer interessant om (na jaren simpelweg Apache + PHP gebruikt te hebben) zelf een 'webserver' te implementeren.