All files / src/implementation location.ts

100% Statements 49/49
100% Branches 10/10
100% Functions 9/9
100% Lines 48/48
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                                        4x           4x     78x 78x     4x 195x     4x 20x 20x     4x 20x 20x     4x   21x 21x       14x   7x 5x   2x       4x 53x 53x     28x 3x     53x 53x 53x 53x     10x   53x 53x                 53x 53x       53x 78x 78x 78x 38x 38x 38x 10x   38x 38x 38x     53x 15x   38x   4x  
/**
 * Copyright 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
/**
 * @fileoverview Functionality related to the parsing/composition of bucket/
 * object location.
 */
import * as errorsExports from './error';
import { errors } from './error';
 
/**
 * @struct
 */
export class Location {
  private path_: string;
 
  constructor(public readonly bucket: string, path: string) {
    this.path_ = path;
  }
 
  get path(): string {
    return this.path_;
  }
 
  fullServerUrl(): string {
    let encode = encodeURIComponent;
    return '/b/' + encode(this.bucket) + '/o/' + encode(this.path);
  }
 
  bucketOnlyServerUrl(): string {
    let encode = encodeURIComponent;
    return '/b/' + encode(this.bucket) + '/o';
  }
 
  static makeFromBucketSpec(bucketString: string): Location {
    let bucketLocation;
    try {
      bucketLocation = Location.makeFromUrl(bucketString);
    } catch (e) {
      // Not valid URL, use as-is. This lets you put bare bucket names in
      // config.
      return new Location(bucketString, '');
    }
    if (bucketLocation.path === '') {
      return bucketLocation;
    } else {
      throw errorsExports.invalidDefaultBucket(bucketString);
    }
  }
 
  static makeFromUrl(url: string): Location {
    let location = null;
    let bucketDomain = '([A-Za-z0-9.\\-]+)';
 
    function gsModify(loc: Location) {
      if (loc.path.charAt(loc.path.length - 1) === '/') {
        loc.path_ = loc.path_.slice(0, -1);
      }
    }
    let gsPath = '(/(.*))?$';
    let path = '(/([^?#]*).*)?$';
    let gsRegex = new RegExp('^gs://' + bucketDomain + gsPath, 'i');
    let gsIndices = { bucket: 1, path: 3 };
 
    function httpModify(loc: Location) {
      loc.path_ = decodeURIComponent(loc.path);
    }
    let version = 'v[A-Za-z0-9_]+';
    let httpRegex = new RegExp(
      '^https?://firebasestorage\\.googleapis\\.com/' +
        version +
        '/b/' +
        bucketDomain +
        '/o' +
        path,
      'i'
    );
    let httpIndices = { bucket: 1, path: 3 };
    let groups = [
      { regex: gsRegex, indices: gsIndices, postModify: gsModify },
      { regex: httpRegex, indices: httpIndices, postModify: httpModify }
    ];
    for (let i = 0; i < groups.length; i++) {
      let group = groups[i];
      let captures = group.regex.exec(url);
      if (captures) {
        let bucketValue = captures[group.indices.bucket];
        let pathValue = captures[group.indices.path];
        if (!pathValue) {
          pathValue = '';
        }
        location = new Location(bucketValue, pathValue);
        group.postModify(location);
        break;
      }
    }
    if (location == null) {
      throw errorsExports.invalidUrl(url);
    }
    return location;
  }
}