1

我有带有 swauth 令牌生成和验证中间件的 openstack swift 组件。现在我无法将大文件上传到其中,我无法在其中寻找。

现在,当我使用令牌对自己进行身份验证时,我将获得没有过期信息的令牌。我开始将文件块上传到其中。这是一个耗时的操作,完成每个文件块需要一段时间。当我的令牌在它中间过期时,我销毁了从 swift 获取 HTTP 401 错误响应,但我销毁了一个块来获取这个,并且由于我无法在我的输入流中寻找我无法重新上传该部分所以我销毁了整个文件只是因为令牌过期?

我知道新的 swauth X-Auth-New-Token 标头功能,它给了我新的令牌,但撤销了旧的。当我这样做时,我会破坏所有其他可以同时上传大文件的客户端。

现在我的问题是如何在没有令牌过期信息的情况下进行身份验证,或者如果返回 HTTP 错误,如何停止从流中读取流内容。

对于上传,我使用 C# HTTPClient 甚至期望 100-continue 添加不会停止流以翻转整个块。

大文件上传的C#代码:

 private readonly HttpClient m_client;
 private bool m_isAuthenticated;

 private void UploadFilePart(string partName, ChunkingStream chunkingStream)
 {

  string requestUrl = RequestUrlBuilder(m_containerName, partName);//GET URL of file
  try
        {
            StreamContent fileContent = new StreamContent(chunkingStream);

            //response = m_client.PutAsync(requestUrl, fileContent).Result;
            var requestMessage = new HttpRequestMessage(HttpMethod.Put, requestUrl);
            requestMessage.Content = fileContent;
            response=m_client.SendAsync(requestMessage,
                                    HttpCompletionOption.ResponseHeadersRead).Result;
            response.EnsureSuccessStatusCode();
        }
        catch (Exception exception)
        {
            //Now when this happens my chunkingStream is shifted and read all data and i cant seek it back.
            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                if (m_log.IsInfoEnabled)
                    m_log.InfoFormat(
                        "It seems that Auth-Token expired. Calling Authenticate method to renew token.");
                Authenticate();
                //re-upload hopefully
                response = m_client.PutAsync(requestUrl, fileContent).Result;
                //fileContent is disposed here so i have to create new one but i dont have data into it since my chunking stream already read whole fileChunk


            }
            if (m_log.IsErrorEnabled)
                m_log.Error("General exception while trying to upload file.", exception);
            throw new InvalidOperationException("Exception while requesting client: ", exception);
        }
 }

注释中请求的 Authenticate 方法的代码:

private void Authenticate()
{
   if (m_log.IsDebugEnabled)
       m_log.DebugFormat("Requesting new token for authentication.");

   const string user = "X-Storage-User";
   const string pass = "X-Storage-Pass";
   const string authUri = "/auth/v1.0";
   const string authKey = "X-Auth-Token";
   const string storageUrl = "X-Storage-Url";

   var request = new HttpRequestMessage(HttpMethod.Get, authUri);
   request.Headers.Add(user, m_configuration.StorageAccount);
   request.Headers.Add(pass, m_configuration.Password);

   HttpResponseMessage response = m_client.SendAsync(request).Result;

   if (response.StatusCode != HttpStatusCode.OK)
   {
       throw new Exception("Authentication Failed. Error: " + response);
   }

   m_authToken = GetResponseHeaderValue(authKey, response);
   //extract only uri following baseAddress
   m_storageUrl = GetResponseHeaderValue(storageUrl, response).Substring(m_configuration.Url.Length);
   //set authentication to true - we are logged
   m_isAuthenticated = true;
   //replace current default authentication header (if exists) with new token key
   m_client.DefaultRequestHeaders.Clear();
   m_client.DefaultRequestHeaders.Add(authKey, m_authToken);
   //set transfer encoding
   m_client.DefaultRequestHeaders.TransferEncodingChunked = true;
}
4

2 回答 2

1

你只需要一个间接层来跟踪你的最后一个块。也许围绕流或流内容的包装器可以做到这一点?通常考虑在复制到内部块缓冲区后从底层流返回数据,当您获得 401 时,调用 myStream.ResetChunk() 并设置一个标志。设置标志后,从内部缓冲区读取数据并清除标志。

于 2013-10-04T14:22:37.020 回答
0

只是好奇; 您不使用 OpenStack .NET SDK 有什么原因吗?我相信这个问题在 SDK 中得到了解决。

于 2013-10-03T20:24:36.170 回答