How to insert data on Grails 3 through REST API? - rest

I've build a demo project on Grails 3.0.10
I can read the data with a REST request but I don't know how to insert data.
Here's how my project is built:
grails create-app bookstore
cd bookstore
grails create-domain-class bookstore.Book
edit file grails-app/domain/bookstore/Book.groovy :
package bookstore
class Book {
String title
String author
Date publicationDate
static constraints = {
}
}
Scaffold:
grails generate-all bookstore.Book
Run the app:
grails run-app
Browse:
http://localhost:8080
From here I can insert and list items from the browser ;o)
Now I want to use the REST API !
Reading data is OK:
curl -H "Accept: application/json" -i http://localhost:8080
/book.jsonHTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 14 Dec 2015 12:14:01 GMT
[{"class":"bookstore.Book","id":1,"author":"James","publicationDate":"2015-12-13T23:00:00Z","title":"Hello"}]
But when I try to insert data:
curl -i -X POST -H "Content-Type: application/json" -H "Accept: application/json" -d '{"title":"Test", "author":"Franck"}'
http://localhost:8080/book/create.jsonHTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Application-Context: application:development
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Mon, 14 Dec 2015 12:16:03 GMT
{"class":"bookstore.Book","id":null,"author":null,"publicationDate":null,"title":null}
And nothing is inserted.

The default create action doesn't save anything. It is used to populate the initial form when creating an instance using a browser form. You probably want to be invoking the save action instead.
This isn't really related to your question but FYI... if you are building a REST interface, you should look at RestfulController and/or the #Resource annotation.

Related

cURL - Setting Content-Type Header is not working?

I'm trying to set the content-type header of my cURL request to application/json.
This is the request I'm using in cmd (I left out the Json-Body):
curl -v -X POST http://localhost:40071/api/Sale --header 'Content-Type: application/json' -d '{[Json Body]}'
When running this command, cURL is logging the following:
Note: Unnecessary use of -X or --request, POST is already inferred.
* Trying 127.0.0.1:40071...
* Connected to localhost (127.0.0.1) port 40071 (#0)
> POST /api/Sale HTTP/1.1
> Host: localhost:40071
> User-Agent: curl/7.79.1
> Accept: */*
> Content-Length: 332
> Content-Type: application/x-www-form-urlencoded
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 500 Internal Server Error
< Date: Tue, 09 Nov 2021 11:18:33 GMT
< Content-length: 0
<
My REST server is running into an exception because of HTTP 415 Unsupported Media Type.
It seems as if cURL did not make use of my "--header" parameter?
Because the log is showing that Content-Type: application/x-www-form-urlencoded was chosen.
I also tried it with the abbreviated parameter "-h".
Seems duplicate question, for more examples, refer here.
How to send a header using a HTTP request through a cURL call?
curl -X POST mockbin.org/request -H "Accept: application/json"

How to add a package to the XQuery repository?

I am using cURL to execute commands using the REST interface of BaseX like this:
curl http://localhost:8984/rest/?command=repo+list
There are also commands to manage the XQuery module repository. I am especially interested in REPO INSTALL to install a package. Is it somehow possible to execute this command using cURL and the REST interface but without having the package already on the target server? I want to provide the file in the body of the cURL request, similar to adding a resource to a database (source) which goes like this:
curl -i -X PUT -T "etc/xml/factbook.xml" "http://localhost:8984/rest/factbook"
Trying
curl -i -X PUT -T "/tmp/foo.xar" http://localhost:8984/rest/?command=repo+install
Gives me
HTTP/1.1 404 Not Found
Content-Type: text/plain;charset=UTF-8
Content-Length: 18
Connection: close
Server: Jetty(9.4.18.v20190429)
No path specified.
Adding -H "Content-Type: application/x-xar" does not help either.
And replacing PUT with POST gives me
HTTP/1.1 100 Continue
HTTP/1.1 400 Bad Request
Date: Tue, 03 Mar 2020 09:53:21 GMT
Content-Type: text/plain;charset=utf-8
Content-Length: 46
Server: Jetty(9.4.18.v20190429)
"" (Line 1): Content is not allowed in prolog.
The following works in case of standard modules (replace user/pass/server if needed):
$ curl http://admin:admin#localhost:8984/rest/?command=repo+install+http://www.xqueryfunctions.com/xq/functx-1.0.1-doc.xq

Grails 2.3.8 RESTful API

I am using Grails 2.3.8 on a Mac.
I hope to use Grails to quickly develop a RESTful API. I started with the basic documentation for Web Services, found here for my version:
http://grails.org/doc/2.3.8/guide/webServices.html#domainResources
This seems to suggest that I can create a simple Domain Class in Grails, then annotate with the #Resource from grails.rest, as follows (straight from the docs above):
import grails.rest.*
#Resource(uri='/books', formats=['json', 'xml'])
class Book {
String title
static constraints = {
title blank:false
}
}
When I place this file into the grails-app/domain directory and run the app, the docs suggest I should be able to use cURL to add "Book" objects via HTTP:
curl -i -X POST -H "Content-Type: application/json" -d '{"title":"Along Came A Spider"}' localhost:8080/myapp/books
But this gives me HTTP 422, with the following message:
HTTP/1.1 422 Unprocessable Entity
Server: Apache-Coyote/1.1
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Tue, 05 Aug 2014 01:46:05 GMT
{"errors":[{"object":"Book","field":"title","rejected-value":null,"message":"Property [title] of class [class Book] cannot be null"}]}
Can anyone advise as to what I am missing here? I expected this to be pretty straightforward.
As #raffian mentioned above in comment, this was due to a bug in Grails 2.3.8:
https://jira.grails.org/browse/GRAILS-11399
Upgrading resolved the issue.

Unable to upload a track using the soundcloud API larger than 7MB

I am unable to upload any tracks larger than about 7MB (413 Request Entity Too Large is returned). This functionality was previously working and the soundcloud api states that tracks can be upto 500MB.
Here is an example using curl with a successful upload(4.9MB) and an unsuccessful one(7.4MB)
I have provided dropbox links to the tracks(my own production, so no copyright issues!!!) if anyone wants to try to replicate. You will need to add your oauth_token.
successful upload = 4900kb_307sec_128kbps_44100hz.mp3
curl -i -X POST "https://api.soundcloud.com/tracks.json" \
-F 'oauth_token=********' \
-F 'track[asset_data]=#4900kb_307sec_128kbps_44100hz.mp3' \
-F 'track[title]=A 4.9MB track' \
-F 'track[sharing]=public'
HTTP/1.1 100 Continue
HTTP/1.1 201 Created
Access-Control-Allow-Headers: Accept, Authorization, Content-Type, Origin
Access-Control-Allow-Methods: GET, PUT, POST, DELETE
Access-Control-Allow-Origin: *
Access-Control-Expose-Headers: Date
Age: 0
Cache-Control: no-cache
Content-Type: application/json; charset=utf-8
Date: Wed, 06 Nov 2013 18:22:57 GMT
Location: https://api.soundcloud.com/tracks/118866401
Server: nginx
Via: 1.1 varnish
X-Cache: MISS
X-Cacheable: NO:Cache-Control=no-cache
X-Runtime: 436
X-Varnish: 3652774389
Content-Length: 1623
unsuccessful upload = 7400kb_307sec_192kbps_44100hz.mp3
curl -i -X POST "https://api.soundcloud.com/tracks.json" \
-F 'oauth_token=********' \
-F 'track[asset_data]=#7400kb_307sec_192kbps_44100hz.mp3' \
-F 'track[title]=A 7.4MB track' \
-F 'track[sharing]=public'
HTTP/1.1 100 Continue
HTTP/1.1 413 Request Entity Too Large
Date: Wed, 06 Nov 2013 18:23:21 GMT
Server: ECS (lhr/4799)
Content-Length: 0
Connection: close
thanks
We have the same issue with soundcloud. Seems to be an issue in their nginx.conf (webserver
configuration).
Please contact Soundcloud support for developers.
Was an issue in SoundCloud API routing. Has been fixed now.
For details see comments at:
Soundcloud: increased 413 failures (Request Entity Too Large) on upload

How to request only for a web page header using netcat?

I am not sure whether netcat has some command for requesting http header or should I use sed to filter the result? If sed is used in this case, is it so that I only have to extract everything before the first "<" occurs ?
The command line tool curl has the -I option which only gets the headers:
-I/--head
(HTTP/FTP/FILE) Fetch the HTTP-header only! HTTP-servers feature the command HEAD which this uses to get nothing but the header of a document. When used on a FTP or FILE file, curl displays the file size and last modification time only.
Demo:
$ curl -I stackoverflow.co.uk
HTTP/1.1 200 OK
Cache-Control: private
Content-Length: 503
Content-Type: text/html; charset=utf-8
Server: Microsoft-IIS/7.5
X-AspNet-Version: 2.0.50727
X-Powered-By: ASP.NET
Date: Thu, 26 Sep 2013 21:06:15 GMT