2012-02-15 24 views
9

Trong ứng dụng iOS của tôi, tôi đang sử dụng UIWebView và giao thức tùy chỉnh (với triển khai NSURLProtocol của chính tôi). Tôi đã khá cẩn thận về đảm bảo rằng bất cứ khi nào tôi tải một url, tôi tải một cái gì đó như thế này vào UIWebView tôi:Sử dụng NSURLProtocol tùy chỉnh với yêu cầu UIWebView và POST

myprotocol: // myserver/mypath

và trong việc thực hiện NSURLProtocol của tôi, tôi phải mất một mutable bản sao của NSURLRequest, chuyển đổi URL thành http: và gửi URL đó đến máy chủ của tôi.

Mọi thứ đều hoạt động đối với các yêu cầu HTTP GET. Vấn đề tôi gặp phải là với yêu cầu POST. Có vẻ như UIWebView không mã hóa đúng dữ liệu biểu mẫu trong HTTPBody nếu yêu cầu sử dụng giao thức tùy chỉnh của tôi.

Một công việc xung quanh, vì tôi đang sử dụng HTTPS cho các yêu cầu máy chủ, tôi đăng ký trình xử lý giao thức để chặn http: thay vì myprotocol: và tôi có thể chuyển đổi tất cả các cuộc gọi thành https: Câu hỏi khác, here, chỉ cho tôi giải pháp đó:

Nhưng tôi tự hỏi nếu có bất kỳ cách thay thế nào và/hoặc tốt hơn để hoàn thành những gì tôi muốn.

Trả lời

5

Thay vì cố gắng sử dụng các yêu cầu POST, một công việc xung quanh là tiếp tục sử dụng các yêu cầu GET cho myprotocol:// URL, nhưng chuyển đổi chúng trong việc thực hiện NSURLProtocol của bạn để yêu cầu http:// POST để máy chủ của bạn bằng cách sử dụng chuỗi truy vấn yêu cầu như nội dung của POST.

Nỗi lo lắng khi sử dụng các yêu cầu GET để gửi lượng lớn dữ liệu là ở đâu đó dọc theo chuỗi yêu cầu, dòng yêu cầu có thể bị cắt bớt. Điều này dường như không phải là một vấn đề, tuy nhiên, với các giao thức được thực hiện tại địa phương.

Tôi đã viết một ứng dụng thử nghiệm ngắn Cordova để thử nghiệm và tôi thấy rằng tôi đã có thể gửi thông qua một ít hơn 1 MiB của dữ liệu mà không gặp rắc rối với các yêu cầu HTTP lặp lại dịch vụ http://http-echo.jgate.de/

Đây là thực hiện startLoading tôi:

- (void)startLoading { 
    NSURL *url = [[self request] URL]; 
    NSString *query = [url query]; 
    // Create a copy of `url` without the query string. 
    url = [[[NSURL alloc] initWithScheme:@"http" host:@"http-echo.jgate.de" path:[url path]] autorelease]; 
    NSMutableURLRequest *newRequest = [NSMutableURLRequest requestWithURL:url]; 
    [newRequest setHTTPMethod:@"POST"]; 
    [newRequest setAllHTTPHeaderFields:[[self request] allHTTPHeaderFields]]; 
    [newRequest addValue:@"close" forHTTPHeaderField:@"Connection"]; 
    [newRequest addValue:@"application/x-www-form-urlencoded;charset=UTF-8" forHTTPHeaderField:@"Content-Type"]; 
    [newRequest setHTTPBody:[query dataUsingEncoding:NSUTF8StringEncoding]]; 
    urlConnection = [[NSURLConnection alloc] initWithRequest:newRequest delegate:self]; 
    if (urlConnection) { 
     receivedData = [[NSMutableData data] retain]; 
    } 
} 

sau đó tôi thực hiện các phương pháp NSURLConnection giao thức để chuyển tiếp đến các phương pháp thích hợp NSURLProtocolClient, nhưng việc xây dựng các dữ liệu phản ứng trong trường hợp Transfer-Encoding:chunked (như trường hợp để được trả lời từ http://http-echo.jgate.de/).

+0

Đề xuất hay. Xin lỗi, tôi đã không nhận thấy câu trả lời của bạn, trước đó. – bcholmes

2

Thật không may, có vẻ như các yêu cầu của đề án http:https: được xử lý hơi khác với các lược đồ khác (bao gồm cả tùy chỉnh) của Khuôn khổ nền tảng. Rõ ràng là HTTPBodyHTTPBodyStream các cuộc gọi có liên quan NSURLRequest trả về luôn nil cho những cái cũ. Điều này đã được quyết định trước cuộc gọi của [NSURLProtocol canInitWithRequest] do đó tùy chỉnh NSURLProtocol thực hiện không có cách nào ảnh hưởng đến điều đó (quá muộn).

Có vẻ như lớp khác nhau NSURLRequest được sử dụng cho http:https: hơn 'mặc định'. Triển khai GnuStep mặc định của lớp này trả về luônnil từ các cuộc gọi HTTPBodyHTTPBodyStream. Do đó, việc triển khai cụ thể (ví dụ: một trong PhoneGap, có thể là một phần của Khung nền tảng), hãy chọn NSURLRequest -loại lớp dựa trên chương trình tư vấn trước đó với NSURLProtocol.Đối với các lược đồ tùy chỉnh, bạn nhận được NSURLRequest trả về nil cho cả hai HTTPBodyHTTPBodyStream, điều này sẽ vô hiệu hóa việc sử dụng phương thức POST (và các phương pháp khác có nội dung) trong trình xử lý lược đồ URI tùy chỉnh.

Có thể có cách để ảnh hưởng đến quyết định trong đó lớp NSURLRequest thực sự được sử dụng nhưng hiện tại tôi chưa biết.

Như một giải pháp thay thế, bạn vẫn có thể sử dụng sơ đồ http: hoặc https: và quyết định trong [NSURLProtocol canInitWithRequest] dựa trên các tiêu chí khác (ví dụ: tên máy chủ).

Các vấn đề liên quan