[Проблема решена, я просто пока не могу выбрать свой ответ в качестве решения.]
Я работаю над функцией загрузки видео для мобильного приложения с API данных YouTube; но у меня по-прежнему возникает ошибка 401 при выполнении запроса.
Я использую Firebase для предоставления ключей OAuth и API от Google Developer.
Я попытался посмотреть, претерпел ли файл PLIST, предоставленный Firebase, какие-либо изменения, и даже с другим.
Я попытался сбросить iOS Simulator, удалить приложение и отменить разрешения моей учетной записи для приложения через GIDSignIn.sharedInstance().disconnect().
Я пытался разобраться с другими вопросами StackOverFlow, но все они касались других языков или даже «сырых» HTTP-запросов.
В моем файле AppDelegate у меня есть эти строки для соединения с Firebase и Google:
FirebaseApp.configure()
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
и этот метод (и очень похожий, который я не буду здесь показывать):
func application( _ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any ) -> Bool {
return GIDSignIn.sharedInstance().handle( url,
sourceApplication: sourceApplication,
annotation: annotation )
}
В моем классе, связанном с контроллером, у меня есть эти методы для создания запроса:
private func uploadVideo( withVideoObject video: GTLRYouTube_Video, resumeUploadLocationURL locationURL: URL? ) throws {
let query = try uploadQuery( _video: video, resumeUploadLocationURL: locationURL )!
// [ progress related feedback ]
YouTubeUploadController.uploadFileTicket = self.service.executeQuery( query,
delegate: self.controller!,
didFinish: #selector( self.controller!.displayResultWithTicket(ticket:finishedWithObject:error:) ) )
}
private func uploadQuery( _video: GTLRYouTube_Video, resumeUploadLocationURL locationURL: URL? ) throws -> GTLRYouTubeQuery_VideosInsert? {
let fileToUploadURL = URL( fileURLWithPath: "\(self.controller!.uploadPathField)" )
if !( try! fileToUploadURL.checkPromisedItemIsReachable() ) {
throw YouTubeCustomError.init( _kind: .fileNotFound )
}
// Get a file handle for the upload data.
let uploadParameters = prepareUploadParameters( fileToUploadURL: fileToUploadURL, locationURL: locationURL )
return GTLRYouTubeQuery_VideosInsert.query( withObject: _video, part: "snippet,status", uploadParameters: uploadParameters )
}
Он отправляет ошибку через displayResultWithTicket(ticket:finishedWithObject:error:):
"Эта операция не может быть завершена. (ошибка com.google.HTTPStatus 401.)"
Не указано ни причины сбоя, ни предложения по восстановлению.
Заранее спасибо.
Текст ответа:
Вот журналы HTTP-ответов GTMSessionFetcher для попытки загрузки:
Response body: (178 bytes)
{
"error" : {
"message" : "Login Required",
"errors" : [
{
"message" : "Login Required",
"locationType" : "header",
"reason" : "required",
"domain" : "global",
"location" : "Authorization"
}
],
"code" : 401
}
}
Заголовки запроса
Request: POST https://www.googleapis.com/resumable/upload/youtube/v3/videos?part=snippet%2Cstatus&prettyPrint=false
Request headers:
Accept: application/json
Cache-Control: no-cache
Content-Type: application/json; charset=utf-8
User-Agent: org.cocoapods.GoogleAPIClientForREST/1.3.8 google-api-objc-client/3.0 iPhone/12.2 hw/sim (gzip) (GTMSUF/1)
X-Goog-Upload-Command: start
X-Goog-Upload-Content-Length: 2614231
X-Goog-Upload-Content-Type: video/mp4
X-Goog-Upload-Protocol: resumable
@stvar отредактировано! Спасибо за предложение ?
Согласно документы, ваша попытка входа в систему не удалась. Не могли бы вы также проверить/опубликовать из журналов инициирующий заголовок HTTP (редактируя любые данные учетных данных!)
Я не уверен, что вы имеете в виду... HTTP-запрос? Кроме того, я не нахожу никаких учетных данных, это из-за POST или я что-то пропустил? ?
Вы знаете, где я должен ввести эти учетные данные?
Возьмем, к примеру, заголовки запросов, показанный здесь. Подозреваю, что у вас нет нужной формы Заголовок HTTP-запросаAuthorization: Bearer ACCESS_TOKEN
Я думаю, что ответ это поможет.
Кажется, я нашел другое решение. Если это сработает, я создам ответ; но я не хочу красть у вас кредит, пока вы мне помогали, поэтому я разрешаю вам публиковать свои ответы, если хотите ?
Совершенно никаких проблем. Идите вперед и опубликуйте свое решение, если оно уже протестировано.
Спасибо. Хорошего дня.





Так что в моем случае мне не хватало влияния авторизатора GTRLService в моем методе входа GIDSignInDelegate:service.authorizer = user.authentication.fetcherAuthorizer()
Я предполагаю, что это можно сделать и другими методами, но это основная точка, в которой он инициализируется.
Я сделал это с помощью средства доступа записи ObjC, потому что не нашел пути к создать/получить экземпляр GTRLService в Swift и использовал одноэлементный класс ObjC для его получения, и я не был уверен, сможем ли мы получить доступ к методам экземпляра GTRLService в Swift, если он был инициализирован в ObjC. .
+ (void)setSharedInstanceAuthorizer:(id <GTMFetcherAuthorizationProtocol>)_authorizer {
if (sharedInstance == nil) {
sharedInstance = [GTLRYouTubeService new];
}
sharedInstance.authorizer = _authorizer;
};
Если это не решит проблему, то могут помочь ответы @stvar в комментариях к вопросу.
Спасибо, что поделились ответом. Но теперь у GTLRYouTubeService больше нет authorizer собственности. Тогда как я могу решить эту проблему? Пожалуйста, дайте мне знать. Спасибо
Не могли бы вы попробовать включить ведение журнала HTTP, чтобы мы могли видеть ответ API в формате JSON?