简体   繁体   中英

expected content type text/json got text/html

I am developing a web service, and am writing a register / login API. When I try and register in the iOS simulator, I get "expected content type text/json got text/html." I have spent hours now trying to debug and find the problem, but am not seeing why I am not getting JSON data.

API.h

#import "AFHTTPClient.h"
#import "AFNetworking.h"

typedef void (^JSONResponseBlock)(NSDictionary* json);

@interface API : AFHTTPClient

@property (strong, nonatomic) NSDictionary *user;

+ (API *)sharedInstance;

//check whether there's an authorized user
-(BOOL)isAuthorized;

//send an API command to the server
-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock;

@end

API.m

#import "API.h"

#define kAPIHost @"http://localhost"
#define kAPIPath @"/api/"

@implementation API

@synthesize user;

+(API*)sharedInstance
{
    static API *sharedInstance = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        sharedInstance = [[self alloc] initWithBaseURL:[NSURL URLWithString:kAPIHost]];
    });

    return sharedInstance;
}

-(API*)init
{
    //call super init
    self = [super init];

    if (self != nil) {
        //initialize the object
        user = nil;

        [self registerHTTPOperationClass:[AFJSONRequestOperation class]];

        // Accept HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
        [self setDefaultHeader:@"Accept" value:@"application/json"];
    }

    return self;
}

-(BOOL)isAuthorized
{
    return [[user objectForKey:@"user_id"] intValue]>0;
}

-(void)commandWithParams:(NSMutableDictionary*)params onCompletion:(JSONResponseBlock)completionBlock
{
    NSMutableURLRequest *apiRequest =
    [self multipartFormRequestWithMethod:@"POST"
                                    path:@"http://localhost/api/index.php"
                              parameters:params
               constructingBodyWithBlock: ^(id <AFMultipartFormData>formData) {
                   //TODO: attach file if needed
               }];

    AFJSONRequestOperation* operation = [[AFJSONRequestOperation alloc] initWithRequest: apiRequest];
    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
        //success!
        completionBlock(responseObject);
    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
        //failure :(
        completionBlock([NSDictionary dictionaryWithObject:[error localizedDescription] forKey:@"error"]);
    }];

    [operation start];
}

@end

index.php

<?
session_start();

require("lib.php");

header("Content-Type:application/json");

switch ($_POST['command'])
{
    case "login":
        login($_POST['username'],$_POST['password']);
        break;
    case "register";
        register($_POST['username'],$_POST['password']);
        break;
}

lib.php

<?php
$link = mysqli_connect("localhost","root","root");
mysqli_select_db($link,"test");

header("Content-Type:application/json");

function errorJson($msg){ 
    print json_encode(array('error'=>$msg));
    exit();
}

function register($user, $pass) {

    //check if username exists in the database (inside the "users" table)
    $login = query("SELECT username FROM users WHERE username='%s' limit 1", $user);

    if (count($login['result'])>0) {

        //the username exists, return error to the iPhone app
        errorJson('Username already exists');
    }

    //try to insert a new row in the "users" table with the given username and password
    $result = query("INSERT INTO users(username, password) VALUES('%s','%s')", $user, $pass);

    if (!$result['error']) {
        //registration is susccessfull, try to also directly login the new user
        login($user, $pass);
    } else {
        //for some database reason the registration is unsuccessfull
        errorJson('Registration failed');
    }

}

CDRegisterViewController.m

- (IBAction)signUp:(id)sender
{
    // form fields validation
    if (self.usernameField.text.length < 4 || self.passwordField.text.length < 4){
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Your password is too short" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
        [alertView show];
    }

    // salt the password
    NSString *saltedPassword = [NSString stringWithFormat:@"%@%@", self.passwordField.text, kSalt];

    // prepare hashed storage
    NSString *hashedPassword = nil;
    unsigned char hashedPasswordData[CC_SHA1_DIGEST_LENGTH];

    //hash the pass
    NSData *data = [saltedPassword dataUsingEncoding:NSUTF8StringEncoding];
    if (CC_SHA1([data bytes], [data length], hashedPasswordData)) {
        hashedPassword = [[NSString alloc] initWithBytes:hashedPasswordData length:sizeof(hashedPasswordData) encoding:NSASCIIStringEncoding];
    } else {
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Password couldn't be sent" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
        [alertView show];
        return;
    }

    // set the parameters to post
    NSString *command = @"register";
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:command, @"command",
                                   self.usernameField.text, @"username", hashedPassword, @"password", nil];

    // make the call to the api
    [[API sharedInstance] commandWithParams:params onCompletion:^(NSDictionary *json)
    {
        //result returned
        NSDictionary* res = [[json objectForKey:@"result"] objectAtIndex:0];

        if ([json objectForKey:@"error"]==nil && [[res objectForKey:@"IdUser"] intValue]>0) {
            //success
            [[API sharedInstance] setUser: res];
            [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

            //show message to the user
            [[[UIAlertView alloc] initWithTitle:@"Logged in"
                                        message:[NSString stringWithFormat:@"Welcome %@",[res objectForKey:@"username"] ]
                                       delegate:nil
                              cancelButtonTitle:@"Close"
                              otherButtonTitles: nil] show];

        } else {
            //error
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Error" message:[json objectForKey:@"error"] delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil];
            [alertView show];
        }
    }];
}

Have you looked at the data to/from the service with an analyzer such as Charles Proxy? That would be the first step--figure out if the problem is on the server or iOS. Next provide some data, the request and the response. Find the end that is incorrect and fix.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM