UIWebView, захватывающий заголовки ответов
Я искал/искал много, но не смог получить ответ о том, как захватить заголовки HTTP-ответа в UIWebview
. Скажем, я перенаправляю пользователя к шлюзу регистрации (который уже активен) в UIWebview при запуске приложения, и когда пользователь заканчивает регистрацию, приложение должно быть уведомлено с успешным уникальным идентификатором, назначенным пользователю при регистрации, который передается обратно в заголовках HTTP-ответов.
Есть ли какой-либо прямой способ захвата/печати заголовков HTTP-ответа с помощью UIWebview
?
Ответы
Ответ 1
Мне нравится среда выполнения objective-c. Есть ли что-то, что вы хотите сделать, но у вас нет API? DM;. HR
Хорошо, на более серьезной ноте, здесь решение этого. Он будет захватывать каждый ответ URL, который инициируется с CFNetwork
, что и используется UIWebView за кулисами. Он также будет захватывать запросы AJAX, загрузки изображений и т.д.
Добавление фильтра к этому, вероятно, должно быть таким же простым, как регулярное выражение для содержимого заголовков.
@implementation NSURLResponse(webViewHack)
static IMP originalImp;
static char *rot13decode(const char *input)
{
static char output[100];
char *result = output;
// rot13 decode the string
while (*input) {
if (isalpha(*input))
{
int inputCase = isupper(*input) ? 'A' : 'a';
*result = (((*input - inputCase) + 13) % 26) + inputCase;
}
else {
*result = *input;
}
input++;
result++;
}
*result = '\0';
return output;
}
+(void) load {
SEL oldSel = sel_getUid(rot13decode("_vavgJvguPSHEYErfcbafr:"));
Method old = class_getInstanceMethod(self, oldSel);
Method new = class_getInstanceMethod(self, @selector(__initWithCFURLResponse:));
originalImp = method_getImplementation(old);
method_exchangeImplementations(old, new);
}
-(id) __initWithCFURLResponse:(void *) cf {
if ((self = originalImp(self, _cmd, cf))) {
printf("-[%s %s]: %s", class_getName([self class]), sel_getName(_cmd), [[[self URL] description] UTF8String]);
if ([self isKindOfClass:[NSHTTPURLResponse class]])
{
printf(" - %s", [[[(NSHTTPURLResponse *) self allHeaderFields] description] UTF8String]);
}
printf("\n");
}
return self;
}
@end
Ответ 2
Нет способа получить объект ответа из UIWebView
(файл с ошибкой с яблоком для этого, скажем, id)
НО два обходных пути
1) через общий NSURLCache
- (void)viewDidAppear:(BOOL)animated {
NSURL *u = [NSURL URLWithString:@"http://www.google.de"];
NSURLRequest *r = [NSURLRequest requestWithURL:u];
[self.webView loadRequest:r];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSCachedURLResponse *resp = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request];
NSLog(@"%@",[(NSHTTPURLResponse*)resp.response allHeaderFields]);
}
@end
, если это работает для вас, это идеальный
ИНАЧЕ
- вы можете использовать NSURLConnection вообще, а затем просто использовать загруженные NSData для подачи
UIWebView
:)
это будет плохой обходной путь для этого! (как заметил Ричард в комментариях.) У этого есть серьезные недостатки, и вы должны убедиться, что это допустимое решение в вашем случае
NSURL *u = [NSURL URLWithString:@"http://www.google.de"];
NSURLRequest *r = [NSURLRequest requestWithURL:u];
[NSURLConnection sendAsynchronousRequest:r queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *resp, NSData *d, NSError *e) {
[self.webView loadData:d MIMEType:nil textEncodingName:nil baseURL:u];
NSLog(@"%@", [(NSHTTPURLResponse*)resp allHeaderFields]);
}];
Ответ 3
Если вы хотите получить более высокий уровень API-кода того, что написал @Richard J. Ross III, вам нужно подклассы NSURLProtocol.
An NSURLProtocol
- это объект, который обрабатывает запросы URL. Таким образом, вы можете использовать его для определенных задач, которые лучше описаны на NSHipster и Ray Wenderlich, который включает ваш случай получения заголовков HTTP из ответа.
код
Создайте новый класс подкласса из NSURLProtocol, и ваш .h файл должен выглядеть следующим образом:
@interface CustomURLProtocol : NSURLProtocol <NSURLConnectionDelegate>
@property (nonatomic, strong) NSURLConnection *connection;
@end
Ваш .m файл должен иметь эти методы для обработки того, что вы хотите для
@implementation CustomURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
// Here you can add custom filters to init or not specific requests
return YES;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
// Here you can modify your request
return request;
}
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [super requestIsCacheEquivalent:a toRequest:b];
}
- (void)startLoading {
// Start request
self.connection = [NSURLConnection connectionWithRequest:self.request delegate:self];
}
- (void) stopLoading {
[self.connection cancel];
self.connection = nil;
}
#pragma mark - Delegation
#pragma mark NSURLConnectionDelegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
// Here we go with the headers
NSDictionary *allHeaderFields = [httpResponse allHeaderFields];
}
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.client URLProtocol:self didLoadData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.client URLProtocolDidFinishLoading:self];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.client URLProtocol:self didFailWithError:error];
}
Также последнее, что нужно сделать, - зарегистрировать этот протокол в системе загрузки, который легко доступен на AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[NSURLProtocol registerClass:[CustomURLProtocol class]];
return YES;
}
Ответ 4
NSHTTPURLResponse
имеет такой метод, как
- (NSDictionary *)allHeaderFields
Для получения дополнительной информации
https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/Reference/Reference.html#//apple_ref/occ/cl/NSHTTPURLResponse
EDIT: Извините, я не думал о UIWebView
. Мое решение работает, если вы используете NSURLConnection
Но если вы загружаете веб-просмотр с помощью NSURLConnection
, тогда у вас есть возможность захватить соединение, включая заголовки ответов.