How to setup resource/:id with RestKit - restkit

My Restful API:
GET http://example.com/articles
GET http://example.com/articles/:id
...
Heres my descriptor setup:
RKResponseDescriptor *responseDescriptorArticleList = [RKResponseDescriptor
responseDescriptorWithMapping:articleMapping
method:RKRequestMethodGET
pathPattern:#"/articles"
keyPath:#nil
statusCodes:[NSIndexSet indexSetWithIndex:200]];
RKResponseDescriptor *responseDescriptorArticle = [RKResponseDescriptor
responseDescriptorWithMapping:articleMapping
method:RKRequestMethodGET
pathPattern:#"/articles/:id"
keyPath:nil
statusCodes:[NSIndexSet indexSetWithIndex:200]];
Function for (GET) http://example.com/articles works
[objectManager getObjectsAtPath:#"/articles"
parameters:nil
success:^sucess{...} failure:^failue{...}];
Function for (GET) http://example.com/articles/:id doesn't work
//Whatever Object is article object or article.id, it doesn't work
[objectManager getObject:Object path:#"/articles/:id"
parameters:nil
success:^sucess{...} failure:^failue{...}];
Server console displays:
GET /articles/:id 404 117ms
Obviously it didn't replace /:id with article.id
I browsed the RestKit documents and examples which looks not updated for 0.20.x, and didn't find the answer. I would be thankful for your help.

Replacements aren't always made into the path pattern. In particular, when calling getObject:path:parameters:success:failure: RestKit is expecting a path, not a path pattern so it will not attempt to replace anything. Your response descriptor is fine, path patterns are always checked there.
getObject:path:parameters:success:failure: will inject into a path pattern if the object is supplied and no path is supplied (path must be nil). In this case the object manager will look for a router which matches the class of the object and the GET request type. So, you need to add a router, something like:
[objectManager.router.routeSet addRoute:[RKRoute routeWithClass:[...Article class] pathPattern:#"/articles/:id" method:RKRequestMethodGET]];

Related

'/' is added to my redirect URL when I try to pass query params

I have a spring app that has a controller to redirect the user to a specific URL based on data they send me. If the data is wrong, I direct them to a url with an error code and description. However, when I do this redirect, it is adding a / before the query parameters, making the redirection wrong. So the code would look like:
Controller.class
String Failure_URL="https://www.google.com";
if(response.getStatus()!=200) {
//there was an error, so redirect to error URL
//map response to my object class
MyObject obj = new MyObject(response);
String redirectURL = Failure_URL + "?error_code=" + obj.getError_Code()
+ "&description=" + obj.getDescription();
}
return new ModelAndView("redirect:" + redirectURL);
When I look at my network trace during testing, I can see the Location header is being set correctly. https://www.google.com?error_code=001&description=System+Error, however when it makes the redirect the URL turns into https://www.google.com/?error_code=SECB001&description=System+Error, making those queryparams a path URI. Is there any way to stop it from doing this, it means these values aren't being set as params correctly. Is this due to the + in the description, and should I encode it?
You should use Spring's UriComponentsBuilder to build URL programmatically and avoid such weird behaviours.
You can build URL like below:
String Failure_URL = UriComponentsBuilder.newInstance()
.scheme("https")
.host("www.google.com")
.queryParam("error_code", "error_code_value")
.queryParam("description", "description_value")
.build().toUriString();
In case you need to add / in URL, you can add .path("/") wherever it is required.

Django REST framework FileField PUT Testcase

I have a model that contains a FileField which may not be blank. When creating tests for this model, I've run into the problem that I get errors when testing with PUT, while the exact same thing works when doing a POST.
As views I'm simply using generics.ListCreateAPIView for the POST destination and generics.RetrieveUpdateDestroyAPIView for the PUT destination, both work normally when using the API in browser.
The payload for the POST and PUT is created as follows:
uploaded_file = SimpleUploadedFile('TestCode4.c', "Testcode", content_type='text/plain')
self.valid_payload = {
'name': 'TestValid',
'test_file': uploaded_file
}
Then the working POST test looks as follows:
client = Client()
response = client.post(
reverse('code-list'),
self.valid_payload,
format='json'
)
And the PUT:
client = Client()
response = client.put(
reverse('code-detail', kwargs={'pk': 1}),
self.valid_payload,
format='json'
)
The POST returns 204 and creates a new object, while the PUT returns 415 with the following error:
{u'detail': u'Unsupported media type "application/octet-stream" in request.'}
I am unsure what is going wrong here, it seems that both the post and put are passing the SimpleUploadedFile data in the same way, though with put it somehow becomes an octet stream.
I figured out the problem Django's django.test.Client class does not support the 'PUT' method. Instead the REST framework provides the class rest_framework.test.APIClient, which does support PUT (and PATCH, etc).
The client.put() function now needs to be filled in a little differently (I was unable to get it to work with SimpleUploadedFile) as explained here: https://fodra.github.io/2017/05/31/testing-django-rest-api-with-image-field.html

WebApi response codes

So let's say I have a WebApi controller called UsersController. Let's look at the following examples:
1.Navigating to /Users/1 returns JSON of a user with Id = 1. HTTP response code will be 200.
2.Navigating to /User/1 (note I misspelled the URL!) will return response code 404. I do not even need to do anything, my web server will return code 404 for me.
Now the question: what response code (200 or 404) should be returned by the URL /Users/2, if user with Id = 2 does not exist in the database? And why.
You should return NotFound (404), because the url is valid but the required resource doesn't exists. check this.

How to receive multiple complex objects using HTTP POST method in Web App

I want to call an web api method, this is how my web api method looks like:
[HttpPost]
[Route("PostMyService/updatedBy/{updatedByID}/myobjname")]
public void PostTerminalService([FromBody] List<SomeType> lstSomeObj, MyClass myobj, int updatedByID)
{
//Do Something
}
This is how my client looks like:
int loggedinuserid=1;
List<Sometype> liTS = new List<SomeType>();
MyClass myobj=new MyClass();
var url = "api/XYZ/PostMyService/updatedBy/" + loggedinuserid + "/myobjname/" + myobj;
HttpResponseMessage response = client1.PostAsJsonAsync(url, liTS).Result;
But the error/exception I am getting is:
HTTP Error 404.0 - Not Found
Most likely causes:
•The directory or file specified does not exist on the Web server.
•The URL contains a typographical error.
•A custom filter or module, such as URLScan, restricts access to the file.
Any idea how to resolve this? I am kind of hitting a wall on this.
Thanks in advance.
You have "api/XYZ/" prefixed in your client code, but I don't see it on your server code. I predict that you have it in your server configuration but if not you will see issues.
You can only have one object with the [FromBody] tag in WebAPI, it's not clear how your trying to pass the MyClass object.
Only simple objects, ints and strings, can be passed in the uri string so the MyClass object will not be transferred correctly.
I would recommend removing the MyClass object or creating a larger object that encapsulates your List<SomeType> andMyClass` and pass that in the body of the request with the [FromBody] decoration.
Here's more information on the topic

CodeIgniter: urlencoded URL in URI segment does not work

I'm trying to put a URL as the value of one of my URI segments in CI. My controller method is defined to accept such an argument. However, when I go to the URL, I get a 404 error. For example:
www.domain.com/foo/urlencoded-url/
Any ideas what's wrong? Should I do this via GET instead?
UPDATE:
// URL that generates 404
http://localhost/myapp/profile_manager/confirm_profile_parent_delete/ugpp_533333338/http%3A%2F%2Flocalhost%2Fmyapp%2Fdashboard%2F
// This is in my profile_manager controller
public function confirm_profile_parent_delete($encrypted_user_group_profile_parent_id = '', $url_current = '')
If I remove the second URI segement, I don't get a 404: http://localhost/myapp/profile_manager/confirm_profile_parent_delete/ugpp_533333338/
It seems that the %2F breaks things for apache.
Possible solutions:
preg_replace the /'s to -'s (or something else) before sending the url then switch it back on the other end.
Set apache to AllowEncodedSlashes On
bit of a hack, but you could even save the url to a session variable or something instead of sending through the url *shrug *
double url encode it before sending
Pass urlendode()'d URL in segment and then decode it with own (MY_*) class:
application/core/MY_URI.php:
class MY_URI extends CI_URI {
function _filter_uri($str)
{
return rawurldecode(parent::_filter_uri($str));
}
}
// EOF
You may need to change the rule in config/route.php to accept the encoded characters in URL. Also you can take a look at some of the solution from below articles:
http://codeigniter.com/forums/viewthread/81365/
http://sholsinger.com/archive/2009/04/passing-email-addresses-in-urls-with-codeigniter/
Passing URL in Codeigniter URL segment
I actually had to do urlencode(urlencode(urlencode(
and urldecode(urldecode(urldecode(
3 times!! and it finally worked, twice didn't cut it.
try
function __autoload($class){
if(!empty($_SERVER['REQUEST_URI'])){
$_SERVER['REQUEST_URI'] = $_SERVER['REDIRECT_QUERY_STRING'] = $_SERVER['QUERY_STRING'] = $_SERVER['REDIRECT_URL'] = $_SERVER['argv'][0] = urldecode($_SERVER['REQUEST_URI']);
}
}
in config.php
this method work for me
This is very old, but I thought I'd share my solution.
Instead of accepting the parameter as a url path, accept it as a get variable:
http://localhost/myapp/profile_manager/confirm_profile_parent_delete/ugpp_533333338?url_current=http%3A%2F%2Flocalhost%2Fmyapp%2Fdashboard%2F
and in code:
function confirm_profile_parent_delete($encrypted_user_group_profile_parent_id = '') {
$url_current = $this->input->get('url_current');
...
This seems to work.

Resources