Reputation: 1102
I am giving a try to use Retrofit 2.0 to implement a library system. Which can add book, list all book info, list one book info, delete one book, delete all books, update one book info.
My baseURL has a '/' in its end:
http://www.example.com/webservice/
The first three features work very well:
@GET("books")
Call<ArrayList<Book>> listBooks();
@POST("books")
Call<Book> addBook(@Body Book book);
@GET("books/{id}")
Call<Book> getBookInfo(@Path("id") int bookId);
However, those three don't work at all:
@DELETE("books/{id}")
Call<Void> deleteBook(@Path("id") int bookId);
@PUT("books/{id}")
Call<Book> updateBook(@Path("id") int bookId , @Body Book book);
@DELETE("clean")
Call<Void> deleteAll();
For example, this is my deleteBook feature:
Gson gson = new GsonBuilder()
.setDateFormat(Constant.DATE_FORMAT)
.create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
LibraryService libraryServiceAPI = retrofit.create(LibraryService.class);
Call<Void> deleteBookCall = libraryServiceAPI.deleteBook(bookId);
deleteBookCall.enqueue(new Callback<Void>() {
@Override
public void onResponse(Call<Void> call, Response<Void> response) {
if (response.isSuccessful()) {
if (response.code() == 204) { // I get 200 here, not 204
// but this is what I find:
// response-->rawResponse-->request-->method == "GET"
// This should be DELETE, am I right?
}
} else {
Log.d(DELETE_BOOK_ERROR, String.valueOf(response.code()));
}
}
@Override
public void onFailure(Call<Void> call, Throwable t) {
Log.d(DELETE_BOOK_ERROR, RESPONSE_FAILURE);
}
});
When I debug the data: I find response-->rawResponse-->request-->method == "GET", which should be "DELETE" in this example. After I implement updateBook and deleteAll features, I find they have the same problem, here the methods both equals to "GET" rather than "PUT" and "DELETE".
Can Someone help me to understand why it happens like this? Thanks a lot.
Update 1: Add screenshot of debug info.
You will see in the response, check the request info, method is "GET", but tag shows method = "DELETE".
Update2: With suggestion from Dexter, I add the HttpLoggingInterceptor for debugging,
HttpLoggingInterceptor logging = new HttpLoggingInterceptor();
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
httpClient.interceptors().add(logging);
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(Constant.BASE_URL)
.addConverterFactory(GsonConverterFactory.create(gson))
.client(httpClient.build()).build();
Here are two pieces of log:
@GET("books/{id}")
Call<Book> getBookInfo(@Path("id") int bookId);
which is correct.03-28 00:26:00.842 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> GET http://www.example.com/56eb7034cada930009ab0998/books/2 http/1.1 03-28 00:26:00.842 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> END GET 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- 200 OK http://www.example.com/56eb7034cada930009ab0998/books/2/ (191ms) 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Connection: keep-alive 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Server: gunicorn/18.0 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Date: Mon, 28 Mar 2016 06:03:30 GMT 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Type: application/json 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Length: 153 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Via: 1.1 vegur 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Sent-Millis: 1459139160940 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Received-Millis: 1459139161040 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: {"author": "123", "categories": "123", "id": 2, "lastCheckedOut": null, "lastCheckedOutBy": null, "publisher": "123", "title": "123", "url": "/books/2/"} 03-28 00:26:01.038 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- END HTTP (153-byte body) 03-28 00:26:01.038 3171-3171/com.xiaoyaoworm.prolificlibrary D/book info response code: Response status code: 200
@DELETE("books/{id}")
Call<Void> deleteBook(@Path("id") int bookId);
which is not correct.03-28 00:26:35.602 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> DELETE http://www.example.com/56eb7034cada930009ab0998/books/2 http/1.1 03-28 00:26:35.602 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: --> END DELETE 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- 200 OK http://www.example.com/56eb7034cada930009ab0998/books/2/ (481ms) 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Connection: keep-alive 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Server: gunicorn/18.0 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Date: Mon, 28 Mar 2016 06:04:05 GMT 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Type: application/json 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Content-Length: 153 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: Via: 1.1 vegur 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Sent-Millis: 1459139195900 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: OkHttp-Received-Millis: 1459139196088 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: {"author": "123", "categories": "123", "id": 2, "lastCheckedOut": null, "lastCheckedOutBy": null, "publisher": "123", "title": "123", "url": "/books/2/"} 03-28 00:26:36.082 3171-3198/com.xiaoyaoworm.prolificlibrary D/OkHttp: <-- END HTTP (153-byte body)
Upvotes: 2
Views: 10857
Reputation: 1102
I find the answer on my own. This is a stupid mistake.....When I debug my response message, I find in my delete and put method, reponse--> rawResponse--> priorResponse: Response{protocol=http/1.1, code=301, message=MOVED PERMANENTLY, url=http://www.example.com/56eb7034cada930009ab0998/clean}
In my correct get function, priorResponse is null. I read HTTP basic information there, finding
If a client issues a GET request to "/testdir/" (i.e., at the directory).......It is interesting to take note that if a client issue a GET request to "/testdir" (without specifying the directory path "/"), the server returns a "301 Move Permanently" with a new "Location" of "/testdir/", as follows.
After adding this "/" as end in my DELETE, PUT interface url, now all the features are working!!! Interesting that in chrome plugin--> Advanced Rest Client, I don't need this "/" in the end to make it work.
My updated interface code now as:
@GET("books")
Call<ArrayList<Book>> listBooks();
@POST("books")
Call<Book> addBook(@Body Book book);
@GET("books/{id}/")
Call<Book> getBookInfo(@Path("id") int bookId);
@DELETE("books/{id}/")
Call<Void> deleteBook(@Path("id") int bookId);
@PUT("books/{id}/")
Call<Book> updateBook(@Path("id") int bookId, @Body Book book);
@DELETE("clean/")
Call<Void> deleteAll();
Upvotes: 7