title: OpenStack swift Token expiration swauth large file upload
body: <p>I have openstack swift component with swauth token generation and validation middleware.
  Now i have problem uploading large files into it with stream in which i can't seek in.</p>
  
  <p>Now when i authenticate myself with token i ll get token with no expiration information.
  I start uploading file chunks into it. This is time consuming operation and it takes a while to complete every file chunk. When my token expires in the middle of it i destroy get HTTP 401 error response from swift BUT i destroyed one chunk to get this, and since i cant seek in my input stream i can't reupload that part so i destroyed whole file just because token expiration?</p>
  
  <p>I know about new swauth  X-Auth-New-Token header feature which give me new token, but revoke old one. When i do that i destroy every other client which could upload large file in the same time.</p>
  
  <p>Now my question is how to authenticate without no token expiration information, or how stop streamcontent to read from stream if HTTP error is on return.</p>
  
  <p>For upload i use C# HTTPClient and even expect 100-continue adding wont stop stream to roll over whole chunk.</p>
  
  <p>C# code for large file upload: </p>
  
  <pre><code> 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);
          }
   }
  </code></pre>
  
  <p>Code for Authenticate method requested in comments:</p>
  
  <pre><code>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;
  }
  </code></pre>