gpt4 book ai didi

ios - Obj-C - POST JSON 数据到服务器?

转载 作者:技术小花猫 更新时间:2023-10-29 11:02:10 24 4
gpt4 key购买 nike

对不起,这个新问题,但我正在为这个问题撕心裂肺。我可以通过 FireFox 的 POSTER 之类的程序成功地将数据发布到我的端点 URL。但是,我正在尝试将相同的 JSON 数据从我的应用程序发布到我的端点 URL(Drupal 服务 push_notifications 端点),但由于某种原因它无法成功发布。这是我正在使用的代码:

ViewController.m

NSString *urlString1 = @"http://app.com/endpoint001/push_notifications";
NSDictionary *jsonBodyDict = @{@"token":postDeviceID, @"type":@"ios"};
NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil];
// watch out: error is nil here, but you never do that in production code. Do proper checks!

NSString *urlString2 = [NSString stringWithFormat:@"http://app.com/endpoint001/push_notifications?token=%@&type=%@",
postDeviceID,@"ios"];

NSMutableURLRequest *request = [NSMutableURLRequest new];
request.HTTPMethod = @"POST";

// for alternative 1:
[request setURL:[NSURL URLWithString:urlString1]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPBody:jsonBodyData];
[request addValue:csrfToken forHTTPHeaderField:@"X-CSRF-Token"];

// for alternative 2:
[request setURL:[NSURL URLWithString:urlString2]];
// no body needed, though that ultimately depends on your server. Also, I didn't test this for lack of a backend :)

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
NSLog(@"Yay, done! Check for errors in response!");

NSHTTPURLResponse *asHTTPResponse = (NSHTTPURLResponse *) response;
NSLog(@"The response is: %@", asHTTPResponse);
// set a breakpoint on the last NSLog and investigate the response in the debugger

// if you get data, you can inspect that, too. If it's JSON, do one of these:
NSDictionary *forJSONObject = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:nil];
// or
NSArray *forJSONArray = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:nil];

NSLog(@"One of these might exist - object: %@ \n array: %@", forJSONObject, forJSONArray);

}];
[task resume];

注:我在用户成功登录后放入了这段代码,所以我不确定是否需要启动一个全新的连接?如果 session 和 CSRF token 已存在,如何将我的数据发布到服务器?我的代码应该是什么样的?回答这个问题的人会出现在我的圣诞名单上...... O_O

NSLog 响应:
2017-07-17 17:31:11.421281-0700 app[977:206852] Yay, done! Check for errors in response!
2017-07-17 17:31:11.422198-0700 app[977:206852] The response is: <NSHTTPURLResponse: 0x170239b40> { URL: http://app.com/endpoint001/push_notifications?token=9526687d594944513b0wabf704eae3223f0de9bf69136a0aae3ab046863474b1&type=ios } { status code: 401, headers {
"Cache-Control" = "no-cache, must-revalidate";
Connection = "keep-alive";
"Content-Type" = "application/json";
Date = "Tue, 18 Jul 2017 00:14:35 GMT";
Expires = "Sun, 19 Nov 1978 05:00:00 GMT";
Server = Apache;
"Transfer-Encoding" = Identity;
Vary = Accept;
"X-Content-Type-Options" = nosniff;
} }
2017-07-17 17:31:27.172085-0700 app[977:207024] XPC connection interrupted
2017-07-17 17:31:27.172311-0700 app[977:206852] One of these might exist - object: (
"CSRF validation failed"
)
array: (
"CSRF validation failed"
)

最佳答案

汤姆的回答给出了正确的方向,但我看到缺乏描述代码实际所做的事情让你感到困惑。此外,您使用的是不推荐使用的方法(来自 NSURLConnection ),所以我使用 NSURLSession 做了一个快速(未经测试)的示例及其相关类。别担心,它基本上是一样的。

话虽如此,您在原始代码中尝试此操作的方式让我怀疑您是否真的在发送 json 正文(即您的后端期望),或者更确切地说系统依赖于无聊的 URL 参数。所以我在我的代码中添加了两种方式:

NSString *postDeviceID = @"something";

NSString *urlString1 = @"http://myurl.com/endpoint01/push_notifications";
NSDictionary *jsonBodyDict = @{@"token":postDeviceID, @"type":@"ios"};
NSData *jsonBodyData = [NSJSONSerialization dataWithJSONObject:jsonBodyDict options:kNilOptions error:nil];
// watch out: error is nil here, but you never do that in production code. Do proper checks!

NSString *urlString2 = [NSString stringWithFormat:@"http://myurl.com/endpoint01/push_notifications?token=%@&type=%@",
postDeviceID,@"ios"];

NSMutableURLRequest *request = [NSMutableURLRequest new];
request.HTTPMethod = @"POST";

// for alternative 1:
[request setURL:[NSURL URLWithString:urlString1]];
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[request setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[request setHTTPBody:jsonBodyData];

// for alternative 2:
[request setURL:[NSURL URLWithString:urlString2]];
// no body needed, though that ultimately depends on your server. Also, I didn't test this for lack of a backend :)

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config
delegate:nil
delegateQueue:[NSOperationQueue mainQueue]];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request
completionHandler:^(NSData * _Nullable data,
NSURLResponse * _Nullable response,
NSError * _Nullable error) {
NSLog(@"Yay, done! Check for errors in response!");

NSHTTPURLResponse *asHTTPResponse = (NSHTTPURLResponse *) response;
NSLog(@"The response is: %@", asHTTPResponse);
// set a breakpoint on the last NSLog and investigate the response in the debugger

// if you get data, you can inspect that, too. If it's JSON, do one of these:
NSDictionary *forJSONObject = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:nil];
// or
NSArray *forJSONArray = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:nil];

NSLog(@"One of these might exist - object: %@ \n array: %@", forJSONObject, forJSONArray);

}];
[task resume];

您的后端也可能支持这两种方式,但学习如何构建合适的 json 主体总是有帮助的。
请注意,tom 的代码让您认为它已发布的原因是您似乎误解了 NSURLConnection有效(除非您排除了您依赖的代码):对象始终按照您使用它的方式构建,因此 if (conn)总是在 YES分支。这并不意味着连接,即实际加载成功。初始值设定项返回 nil如果它不能创建一个实例,而不是一个有效的实例仅仅依赖于连接到它的目标时被拒绝的数据。您不会以这种方式收到错误消息(您需要为此依赖委托(delegate))。

我展示的 session 方法为您提供了一个完成块,您可以在其中调查服务器响应的内容,以进一步追踪出了什么问题。您可以在那里设置一个断点并查看错误(如果成功则为 nil)、响应中的状态等。

我显然没有运行这个确切的代码,所以请原谅任何错别字,但是我经常使用这种方法从我的日常工作中加载和发送到各种后端。一般来说,它应该可以工作(并且,更重要的是,允许您弄清楚后端期望什么,假设您没有关于它的详细文档)。

编辑 :

好的,代码注释中的提示可能具有误导性:我的意思是检查响应是否有错误。 response对象(另请参阅 dataTask... 方法的一般文档)。我添加了一些帮助代码,但请注意 data 的转换将对象转换为 JSON 取决于您的服务器是否实际传递任何数据以及是否传递任何数据。或者它可能有一个奇怪的格式或其他东西,你需要弄清楚这一点。对于 POST 的简单内容,它可能不提供任何数据,您只需在 response 中获得有关它是否有效的相应信息。 .特别注意 NSHTTPURLResponsestatusCode属性(property)。除非你的服务器做了一些奇怪的事情,否则就是 HTTP status code由标准定义,应该可以帮助你。例如,如果您在请求中构建正文的方式(在我的示例代码中为 jsonBodyDict)是错误的(元素名称错误等),您将得到 400。

一般来说,您必须了解“错误”的含义在这里并不那么简单。这些方法将根本无法连接视为错误,因此在这些情况下,您会在完成块中获得一个错误对象。当您的服务器根本不存在或类似情况时,通常会出现这种情况。但是,如果您只是未能将您想要的信息传达给您的服务器,那么从 API 的角度来看,这不是错误,您也不会得到错误对象。您会收到一个有效的响应,指出“此请求是错误的”。在您的情况下,您已经做得很好,因为连接似乎已经发生并正常工作,您只是还没有发送服务器期望的数据。 response应该提供更多信息。

进一步调试这将超出这个问题的范围,因为最终我们正在讨论您的特定后端现在的行为方式。如果你无法弄清楚,你需要给我你的服务器的凭据,以便我可以自己测试,其他一切现在都由我来猜测。 :) 我们可以这样做,但最好在聊天中这样做,而不是在已经那么长的问题/答案中这样做,呵呵。

关于ios - Obj-C - POST JSON 数据到服务器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44814745/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com