changeset 146:de02414174dc

Update generated code
author Lewin Bormann <lbo@spheniscida.de>
date Tue, 27 Oct 2020 10:41:42 +0100
parents 0f6f369a8539
children 96af5d68fada
files drive_example/src/drive_v3_types.rs gcs_example/src/storage_v1_types.rs
diffstat 2 files changed, 844 insertions(+), 124 deletions(-) [+]
line wrap: on
line diff
--- a/drive_example/src/drive_v3_types.rs	Tue Oct 27 10:41:33 2020 +0100
+++ b/drive_example/src/drive_v3_types.rs	Tue Oct 27 10:41:42 2020 +0100
@@ -3854,6 +3854,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl AboutService {
@@ -3868,7 +3871,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -3886,7 +3922,7 @@
     /// Gets information about the user, the user's Drive, and system capabilities.
     pub async fn get(&mut self, params: &AboutGetParams) -> Result<About> {
         let rel_path = format!("about",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -3918,6 +3954,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ChangesService {
@@ -3932,7 +3971,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -3953,7 +4025,7 @@
         params: &ChangesGetStartPageTokenParams,
     ) -> Result<StartPageToken> {
         let rel_path = format!("changes/startPageToken",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -3982,7 +4054,7 @@
     /// Lists the changes for a user or shared drive.
     pub async fn list(&mut self, params: &ChangesListParams) -> Result<ChangeList> {
         let rel_path = format!("changes",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4011,7 +4083,7 @@
     /// Subscribes to changes for a user.
     pub async fn watch(&mut self, params: &ChangesWatchParams, req: &Channel) -> Result<Channel> {
         let rel_path = format!("changes/watch",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4044,6 +4116,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ChannelsService {
@@ -4058,7 +4133,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -4076,7 +4184,7 @@
     /// Stop watching resources through this channel
     pub async fn stop(&mut self, params: &ChannelsStopParams, req: &Channel) -> Result<()> {
         let rel_path = format!("channels/stop",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4109,6 +4217,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl CommentsService {
@@ -4123,7 +4234,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -4148,7 +4292,7 @@
             "files/{fileId}/comments",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4182,7 +4326,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4215,7 +4359,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4247,7 +4391,7 @@
             "files/{fileId}/comments",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4284,7 +4428,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4317,6 +4461,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl DrivesService {
@@ -4331,7 +4478,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -4349,7 +4529,7 @@
     /// Creates a new shared drive.
     pub async fn create(&mut self, params: &DrivesCreateParams, req: &Drive) -> Result<Drive> {
         let rel_path = format!("drives",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4382,7 +4562,7 @@
             "drives/{driveId}",
             driveId = percent_encode(params.drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4414,7 +4594,7 @@
             "drives/{driveId}",
             driveId = percent_encode(params.drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4446,7 +4626,7 @@
             "drives/{driveId}/hide",
             driveId = percent_encode(params.drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4475,7 +4655,7 @@
     /// Lists the user's shared drives.
     pub async fn list(&mut self, params: &DrivesListParams) -> Result<DriveList> {
         let rel_path = format!("drives",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4507,7 +4687,7 @@
             "drives/{driveId}/unhide",
             driveId = percent_encode(params.drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4539,7 +4719,7 @@
             "drives/{driveId}",
             driveId = percent_encode(params.drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4572,6 +4752,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl FilesService {
@@ -4586,7 +4769,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -4607,7 +4823,7 @@
             "files/{fileId}/copy",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4637,7 +4853,7 @@
     /// Creates a new file.
     pub async fn create(&mut self, params: &FilesCreateParams, req: &File) -> Result<File> {
         let rel_path = format!("files",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4674,7 +4890,7 @@
         data: hyper::body::Bytes,
     ) -> Result<File> {
         let rel_path = format!("/upload/drive/v3/files",);
-        let path = "https://www.googleapis.com/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4714,7 +4930,7 @@
         req: &File,
     ) -> Result<ResumableUpload<'client, File>> {
         let rel_path = format!("/resumable/upload/drive/v3/files",);
-        let path = "https://www.googleapis.com/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4762,7 +4978,7 @@
             "files/{fileId}",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4791,7 +5007,7 @@
     /// Permanently deletes all of the user's trashed files.
     pub async fn empty_trash(&mut self, params: &FilesEmptyTrashParams) -> Result<()> {
         let rel_path = format!("files/trash",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4828,7 +5044,7 @@
             "files/{fileId}/export",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4857,7 +5073,7 @@
     /// Generates a set of file IDs which can be provided in create or copy requests.
     pub async fn generate_ids(&mut self, params: &FilesGenerateIdsParams) -> Result<GeneratedIds> {
         let rel_path = format!("files/generateIds",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4894,7 +5110,7 @@
             "files/{fileId}",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4923,7 +5139,7 @@
     /// Lists or searches files.
     pub async fn list(&mut self, params: &FilesListParams) -> Result<FileList> {
         let rel_path = format!("files",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4955,7 +5171,7 @@
             "files/{fileId}",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4995,7 +5211,7 @@
             "/upload/drive/v3/files/{fileId}",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5046,7 +5262,7 @@
             "/resumable/upload/drive/v3/files/{fileId}",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5101,7 +5317,7 @@
             "files/{fileId}/watch",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5134,6 +5350,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl PermissionsService {
@@ -5148,7 +5367,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5173,7 +5425,7 @@
             "files/{fileId}/permissions",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5207,7 +5459,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             permissionId = percent_encode(params.permission_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5240,7 +5492,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             permissionId = percent_encode(params.permission_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5272,7 +5524,7 @@
             "files/{fileId}/permissions",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5309,7 +5561,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             permissionId = percent_encode(params.permission_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5342,6 +5594,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl RepliesService {
@@ -5356,7 +5611,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5378,7 +5666,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5413,7 +5701,7 @@
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC),
             replyId = percent_encode(params.reply_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5447,7 +5735,7 @@
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC),
             replyId = percent_encode(params.reply_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5480,7 +5768,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5514,7 +5802,7 @@
             commentId = percent_encode(params.comment_id.as_bytes(), NON_ALPHANUMERIC),
             replyId = percent_encode(params.reply_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5547,6 +5835,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl RevisionsService {
@@ -5561,7 +5852,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5583,7 +5907,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             revisionId = percent_encode(params.revision_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5621,7 +5945,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             revisionId = percent_encode(params.revision_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5653,7 +5977,7 @@
             "files/{fileId}/revisions",
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5690,7 +6014,7 @@
             fileId = percent_encode(params.file_id.as_bytes(), NON_ALPHANUMERIC),
             revisionId = percent_encode(params.revision_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5723,6 +6047,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl TeamdrivesService {
@@ -5737,7 +6064,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://www.googleapis.com/drive/v3/".into(),
+            root_url: "https://www.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5759,7 +6119,7 @@
         req: &TeamDrive,
     ) -> Result<TeamDrive> {
         let rel_path = format!("teamdrives",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5792,7 +6152,7 @@
             "teamdrives/{teamDriveId}",
             teamDriveId = percent_encode(params.team_drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5824,7 +6184,7 @@
             "teamdrives/{teamDriveId}",
             teamDriveId = percent_encode(params.team_drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5853,7 +6213,7 @@
     /// Deprecated use drives.list instead.
     pub async fn list(&mut self, params: &TeamdrivesListParams) -> Result<TeamDriveList> {
         let rel_path = format!("teamdrives",);
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5889,7 +6249,7 @@
             "teamdrives/{teamDriveId}",
             teamDriveId = percent_encode(params.team_drive_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://www.googleapis.com/drive/v3/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
--- a/gcs_example/src/storage_v1_types.rs	Tue Oct 27 10:41:33 2020 +0100
+++ b/gcs_example/src/storage_v1_types.rs	Tue Oct 27 10:41:42 2020 +0100
@@ -4393,6 +4393,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl BucketAccessControlsService {
@@ -4407,7 +4410,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -4429,7 +4465,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4465,7 +4501,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4501,7 +4537,7 @@
             "b/{bucket}/acl",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4537,7 +4573,7 @@
             "b/{bucket}/acl",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4574,7 +4610,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4612,7 +4648,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4645,6 +4681,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl BucketsService {
@@ -4659,7 +4698,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -4680,7 +4752,7 @@
             "b/{bucket}",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4712,7 +4784,7 @@
             "b/{bucket}",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4744,7 +4816,7 @@
             "b/{bucket}/iam",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4773,7 +4845,7 @@
     /// Creates a new bucket.
     pub async fn insert(&mut self, params: &BucketsInsertParams, req: &Bucket) -> Result<Bucket> {
         let rel_path = format!("b",);
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4803,7 +4875,7 @@
     /// Retrieves a list of buckets for a given project.
     pub async fn list(&mut self, params: &BucketsListParams) -> Result<Buckets> {
         let rel_path = format!("b",);
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4838,7 +4910,7 @@
             "b/{bucket}/lockRetentionPolicy",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4870,7 +4942,7 @@
             "b/{bucket}",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4907,7 +4979,7 @@
             "b/{bucket}/iam",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4943,7 +5015,7 @@
             "b/{bucket}/iam/testPermissions",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -4975,7 +5047,7 @@
             "b/{bucket}",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5008,6 +5080,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ChannelsService {
@@ -5022,7 +5097,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5040,7 +5148,7 @@
     /// Stop watching resources through this channel
     pub async fn stop(&mut self, params: &ChannelsStopParams, req: &Channel) -> Result<()> {
         let rel_path = format!("channels/stop",);
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5073,6 +5181,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl DefaultObjectAccessControlsService {
@@ -5087,7 +5198,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5109,7 +5253,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5145,7 +5289,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5181,7 +5325,7 @@
             "b/{bucket}/defaultObjectAcl",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5217,7 +5361,7 @@
             "b/{bucket}/defaultObjectAcl",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5254,7 +5398,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5292,7 +5436,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5325,6 +5469,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl NotificationsService {
@@ -5339,7 +5486,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5361,7 +5541,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             notification = percent_encode(params.notification.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5394,7 +5574,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             notification = percent_encode(params.notification.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5430,7 +5610,7 @@
             "b/{bucket}/notificationConfigs",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5463,7 +5643,7 @@
             "b/{bucket}/notificationConfigs",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5495,6 +5675,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ObjectAccessControlsService {
@@ -5509,7 +5692,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5532,7 +5748,7 @@
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5569,7 +5785,7 @@
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5606,7 +5822,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5643,7 +5859,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5681,7 +5897,7 @@
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5720,7 +5936,7 @@
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC),
             entity = percent_encode(params.entity.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5753,6 +5969,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ObjectsService {
@@ -5767,7 +5986,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -5795,7 +6047,7 @@
             destinationObject =
                 percent_encode(params.destination_object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5833,7 +6085,7 @@
             destinationObject =
                 percent_encode(params.destination_object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5867,7 +6119,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5905,7 +6157,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5938,7 +6190,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -5970,7 +6222,7 @@
             "b/{bucket}/o",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6010,7 +6262,7 @@
             "/upload/storage/v1/b/{bucket}/o",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6053,7 +6305,7 @@
             "/resumable/upload/storage/v1/b/{bucket}/o",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6101,7 +6353,7 @@
             "b/{bucket}/o",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6134,7 +6386,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6168,7 +6420,7 @@
         req: &Object,
     ) -> Result<RewriteResponse> {
         let rel_path = format!("b/{sourceBucket}/o/{sourceObject}/rewriteTo/b/{destinationBucket}/o/{destinationObject}", sourceBucket=percent_encode(params.source_bucket.as_bytes(), NON_ALPHANUMERIC),sourceObject=percent_encode(params.source_object.as_bytes(), NON_ALPHANUMERIC),destinationBucket=percent_encode(params.destination_bucket.as_bytes(), NON_ALPHANUMERIC),destinationObject=percent_encode(params.destination_object.as_bytes(), NON_ALPHANUMERIC));
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6206,7 +6458,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6243,7 +6495,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6276,7 +6528,7 @@
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC),
             object = percent_encode(params.object.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6313,7 +6565,7 @@
             "b/{bucket}/o/watch",
             bucket = percent_encode(params.bucket.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6346,6 +6598,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ProjectsService {
@@ -6360,7 +6615,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -6381,6 +6669,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ProjectsHmacKeysService {
@@ -6395,7 +6686,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -6416,7 +6740,7 @@
             "projects/{projectId}/hmacKeys",
             projectId = percent_encode(params.project_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6449,7 +6773,7 @@
             projectId = percent_encode(params.project_id.as_bytes(), NON_ALPHANUMERIC),
             accessId = percent_encode(params.access_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6482,7 +6806,7 @@
             projectId = percent_encode(params.project_id.as_bytes(), NON_ALPHANUMERIC),
             accessId = percent_encode(params.access_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6514,7 +6838,7 @@
             "projects/{projectId}/hmacKeys",
             projectId = percent_encode(params.project_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6551,7 +6875,7 @@
             projectId = percent_encode(params.project_id.as_bytes(), NON_ALPHANUMERIC),
             accessId = percent_encode(params.access_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;
@@ -6584,6 +6908,9 @@
     client: TlsClient,
     authenticator: Box<dyn 'static + std::ops::Deref<Target = Authenticator>>,
     scopes: Vec<String>,
+
+    base_url: String,
+    root_url: String,
 }
 
 impl ProjectsServiceAccountService {
@@ -6598,7 +6925,40 @@
             client: client,
             authenticator: Box::new(auth),
             scopes: vec![],
-        }
+            base_url: "https://storage.googleapis.com/storage/v1/".into(),
+            root_url: "https://storage.googleapis.com/".into(),
+        }
+    }
+
+    /// Provide the base URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn base_url(&self) -> String {
+        if self.base_url.ends_with("/") {
+            return self.base_url.clone();
+        }
+        return self.base_url.clone() + "/";
+    }
+    /// Provide the root URL of this API. The returned URL is guaranteed to end with a '/'.
+    fn root_url(&self) -> String {
+        if self.root_url.ends_with("/") {
+            return self.root_url.clone();
+        }
+        return self.root_url.clone();
+    }
+    /// Returns appropriate URLs for relative and absolute paths.
+    fn format_path(&self, path: &str) -> String {
+        if path.starts_with("/") {
+            return self.root_url().trim_end_matches("/").to_string() + path;
+        } else {
+            return self.base_url() + path;
+        }
+    }
+
+    #[cfg(test)]
+    /// Override API URLs. `base` is the base path relative to which (relative) method paths are interpreted,
+    /// whereas `root` is the URL relative to which absolute paths are interpreted.
+    fn set_urls(&mut self, base: String, root: String) {
+        self.base_url = base;
+        self.root_url = root;
     }
 
     /// Explicitly select which scopes should be requested for authorization. Otherwise,
@@ -6622,7 +6982,7 @@
             "projects/{projectId}/serviceAccount",
             projectId = percent_encode(params.project_id.as_bytes(), NON_ALPHANUMERIC)
         );
-        let path = "https://storage.googleapis.com/storage/v1/".to_string() + &rel_path;
+        let path = self.format_path(rel_path.as_str());
 
         let mut headers = vec![];
         let tok;