Question

I have a Django backend platform in which I implemented an API using django-rest-framework.

I have an iOS app in which I use AFNetworking2.0 to interact with my API, both using GET and POST, depending on the situation.

When I'm running the whole platform in local (using the Django internal runserver), everything works fine.

When running the backend with Apache, an strange problem happens. The first request (no matter GET or POST) my iOS app makes to any method handled by django-rest-framework ends up in a 302 redirect to the same method, but losing all the parameters. For example, this the log of Apache for my method "districts":

With GET: 189.122.X.X - - [07/May/2014:14:16:50 +0200] "GET /recursos/api/districts/?city_id=3 HTTP/1.1" 302 548 189.122.X.X - - [07/May/2014:14:16:51 +0200] "GET /recursos/api/districts/ HTTP/1.1" 200 399

And with POST: 189.122.X.X - - [07/May/2014:14:16:15 +0200] "POST /recursos/api/districts/ HTTP/1.1" 302 548 189.122.X.X - - [07/May/2014:14:16:16 +0200] "GET /recursos/api/districts/ HTTP/1.1" 200 399

Some interesting tests:

  1. Any subsequent GET/POST request from the iOS app to this API after a few seconds have gone by, works properly
  2. If I make the request via Browser, no matter when, it works properly: doesn't 302 redirect and handles the request properly
  3. Request from inside the app makes to methods not being part of the django-rest-framework api, works properly

I don't know what else to do in order to get this working in all those scenarios.

For it to work right now, I have to make a first call that I know it will fail. And wait some seconds until doing the second, that will work. Because doing it immediately it will fail again.

The AFNetworking call looks like:

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
    manager.responseSerializer = [AFJSONResponseSerializer serializer];
    NSString *method = [NSString stringWithFormat:@"%@%@", SERVER_URL, @"ws_districts"];
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    [dict setValue:@"3" forKey:@"city_id"];
    [manager GET:method
      parameters:dict
         success:^(AFHTTPRequestOperation *operation, id responseObject) {
             NSLog(@"%@ %i",responseObject,city.o_id);
         }
         failure:^(AFHTTPRequestOperation *operation, NSError *error) {
             NSLog(@"%@",error);
         }];

In the django-rest-framework I use a serializer:

class DistrictSerializer(serializers.ModelSerializer):
class Meta:
    model = District
    fields = ('id', 'name')

A method in my view:

@csrf_exempt
def districts(request):
if request.method == 'GET':
    city_id = request.GET.get('city_id', None)

    queryset = District.objects.filter(city_id=city_id)

    serializer_context = {'request': request}
    serializer = DistrictSerializer(queryset, context=serializer_context)

    response = JSONResponse(serializer.data)
    return response

elif request.method == 'POST':
    data = JSONParser().parse(request)
    serializer = DistrictSerializer(data=data)
    if serializer.is_valid():
        serializer.save()
        return JSONResponse(serializer.data, status=201)
    return JSONResponse(serializer.errors, status=400)

And the url:

urlpatterns = patterns('views.api',
url(r'^api/districts/$', 'districts'),

Any hint?

Was it helpful?

Solution

I finally found the problem some time ago: it was all related to the HTTP Accept-Language header.

Our Django app defines the following languages:

LANGUAGES = (
('en', ugettext('En')),
('pt', ugettext('Pt')),
('es', ugettext('Es')))

When sending the request without specifying the AcceptLanguage header, it would end up on a 302.

By sending the request with "en-US,en;q=0.8,pt;q=0.6,es;q=0.4", it works fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top