List Browsable URLs Function
    • Dark
      Light

    List Browsable URLs Function

    • Dark
      Light

    Article Summary

    This next video provides an alternative way of exploring the sample application and reviewing the topics that follow immediately below:

    Function list_objects_browsable_url()

    Next up is another read-only operation using function list_objects_browsable_url(). This function has similarities to the earlier function list_object_keys(). In fact, it will call list_object_keys(), however it has additional logic to construct and return a valid, browsable URL for each object. The logic in function list_objects_browsable_url() does this by concatenating the bucket's regional endpoint, the bucket name, and each object's key. This can be especially helpful for buckets with access set to Public.

    Before looking at the logic in the function, let's first look at the conditional block in the main() function that will invoke it. Following is the full logic of this block.

    # 02 - List Objects formatted as browsable url
        # IF *PUBLIC* BUCKET, PRINT OUTPUTS BROWSABLE URL FOR EACH FILE IN THE BUCKET
        elif len(args) == 1 and (args[0] == '02' or args[0] == '02PUB'):
            # Call function to return list of object 'keys' concatenated into friendly urls
            browsable_urls = list_objects_browsable_url(PUBLIC_BUCKET_NAME, endpoint, b2)
            for url in browsable_urls:
                print(url)
    
            print('\nBUCKET ', PUBLIC_BUCKET_NAME, ' CONTAINS ', 
                  len(browsable_urls), ' OBJECTS')

    Following is the conditional else if logic for the second block. This block is executed if an argument is passed (len(args) == 1), and if the value of the input parameter is either "02" or "02PUB" (args[0] == '02' or args[0] == '02PUB').

     # 02 - List Objects formatted as browsable url
        # IF *PUBLIC* BUCKET, PRINT OUTPUTS BROWSABLE URL FOR EACH FILE IN THE BUCKET
        elif len(args) == 1 and (args[0] == '02' or args[0] == '02PUB'):

    When logic for this block resolves to true, it executes the sample application function list_objects_browsable_url(). Note that this call is passing in three parameters: PUBLIC_BUCKET_NAME, endpoint, and b2. All three input parameters and how they were created was described above.

     # Call function to return list of object 'keys' concatenated into friendly urls
            browsable_urls = list_objects_browsable_url(PUBLIC_BUCKET_NAME, endpoint, b2)

    Before discussing the remaining logic in this conditional block in main(), let's first review the logic inside the function list_objects_browsable_url().

    Following are the lines of code you will find in the sample application defining the function list_objects_browsable_url():

    # List browsable URLs of the objects in the specified bucket - Useful for *PUBLIC* buckets
    def list_objects_browsable_url(bucket, endpoint, b2):
        try:
            bucket_objects = list_object_keys(bucket, b2)
    
            return_list = []               # create empty list
            for url in bucket_object_keys: # iterate bucket_objects 
                url = "%s/%s/%s" % (endpoint, bucket, url) # format and concatenate 
                                           # strings as valid url 
                return_list.append(url)    # for each item in bucket_objects, 
                                           # append value of 'url' to list
            return return_list             # return list of keys from response
    
        except ClientError as ce:
            print('error', ce)

    Following is sample output from the execution of list_objects_browsable_url() (after print() output in main()):

    python sample.py
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/.bzEmpty
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/.bzEmpty
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    carousel-slider.uiinitiative.com-index.ed866659.css
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    index.b1995cd6.js
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    [email protected]~swiper-bundle.min.css
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    [email protected]~swiper-bundle.min.js
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    vendor.50b6404e.js
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/carousel.html
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/photos.html
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/beach.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/bobcat.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/coconuts.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/lake.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/sunset.jpg
    
    BUCKET developer-b2-quick-start CONTAINS 14 OBJECTS
    
    Process finished with exit code 0

    So, let's step through the logic of the function list_objects_browsable_url(). First, the function's signature specifies three input arguments: bucket, endpoint, and b2. As we saw in the calling code back in main(), the value passed to the bucket will be a string containing the name of the bucket to be referenced. The value passed to endpoint will be a string containing the name of the Backblaze B2 Cloud Storage S3-Compatible API endpoint (that earlier logic in main() retrieved from a constant ENDPOINT in .env). Lastly, the b2 argument must be a reference to a valid Backblaze B2 resource service object.

    # List browsable URLs of the objects in the specified bucket
    # Useful for *PUBLIC* buckets
    def list_objects_browsable_url(bucket, endpoint, b2):
    

    Inside the function there are two blocks, try: and except. For our review of the functions in this sample application, we will focus solely on the logic in the try: blocks. For the sample application the except blocks contain only simple print() statements. For details on error handling in boto3, please see the documentation here.

    # List browsable URLs of the objects in the specified bucket
    # Useful for *PUBLIC* buckets
    def list_objects_browsable_url(bucket, endpoint, b2):
        try:
            ...
    
        except ClientError as ce:
            print('error', ce)
    

    The sample application includes the following among required statements at the top of the application:

    from botocore.exceptions import ClientError

    Now, let's step through the logic in the try block. First, we take two of the input arguments and invoke the function list_object_keys(bucket, b2) (that was reviewed above), storing the returned iterable collection of object key values in a local variable named bucket_objects. In processing this function call, the logic communicates with the backend Backblaze B2 service and the Backblaze B2 service sends back the iterable collection of ObjectSummary resources, which the logic in function list_object_keys() iterates over and extracts just the key values, which are then returned from function list_object_keys().

            bucket_objects = list_object_keys(bucket, b2)

    The intent of the list_objects_browsable_url() function is to return an iterable collection of strings that are valid browsable URLs for each object. The next four lines start by declaring a local variable return_list as an empty list which the next three lines will populate as the logic iterates over the return_list collection. The next line uses a for statement to iterate over the bucket_objects extracting each of those objects' key values. The third line uses the Python formatting "%" operator to concatenate three variable values with literal "/" between each, storing the results in variable url. This operator creates a single string using the %s operator. In execution of this line of code, the strings are replaced in the order of their position in the brackets, wherever there is a %s sign. Then the last line uses the append() method on the list return_list to add each url to the collection.

    return_list = []               # create empty list
        for key in bucket_objects:     # iterate bucket_objects
            url = "%s/%s/%s" % (endpoint, bucket, key)
            return_list.append(url)    # for each item in bucket_objects,
                                       # append value of 'url' to list

    The function's processing is now complete and the last line uses the return statement to return back the reference to return_list.

        return return_list             # return list of keys from response

    For the sample application, processing now continues back in the main() function conditional block that called list_objects_browsable_url(PUBLIC_BUCKET_NAME, endpoint, b2). The following is the full logic of this calling block.

    # 02 - List Objects formatted as browsable url
        # IF *PUBLIC* BUCKET, PRINT OUTPUTS BROWSABLE URL FOR EACH FILE IN THE BUCKET
        elif len(args) == 1 and (args[0] == '02' or args[0] == '02PUB'):
            # Call function to return list of object 'keys' concatenated into 
            # friendly urls
            browsable_urls = list_objects_browsable_url(PUBLIC_BUCKET_NAME, endpoint, b2)
            for url in browsable_urls:
                print(url)
    
            print('\nBUCKET ', PUBLIC_BUCKET_NAME, ' CONTAINS ', 
                  len(browsable_urls), ' OBJECTS')

    Thus, execution of this line of code is now complete. And the variable browsable_urls now contains an iterable collection of valid browsable URLs for each object.

        browsable_urls = list_objects_browsable_url(PUBLIC_BUCKET_NAME, endpoint, b2)

    The remainder of the logic here in the conditional block generates print() output to display the returned results.

    The next two lines use a for statement to first iterate over the browsable_urls, extracting from each a reference to each url in the collection. The second line uses a print() statement to display the url value of each item in the collection.

        for url in browsable_urls:
            print(url)

    Last, the the conditional block closes with the following print() statement to display the PUBLIC_BUCKET_NAME and a count of the number of keys returned by the call using the logic of len(browsable_urls). These two variable values are concatenated with the literal strings to display output such as:

    BUCKET developer-b2-quick-start CONTAINS 14 OBJECTS

        print('\nBUCKET ', PUBLIC_BUCKET_NAME, ' CONTAINS ', 
              len(browsable_urls), ' OBJECTS')

    Recapping and repeating, the following is sample output from the execution of list_objects_browsable_url() and the print() statements following its execution in main():

    python sample.py
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/.bzEmpty
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/.bzEmpty
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    carousel-slider.uiinitiative.com-index.ed866659.css
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    index.b1995cd6.js
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    [email protected]~swiper-bundle.min.css
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    [email protected]~swiper-bundle.min.js
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/assets/
    vendor.50b6404e.js
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/carousel.html
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/album/photos.html
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/beach.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/bobcat.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/coconuts.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/lake.jpg
    https://s3.us-west-002.backblazeb2.com/developer-b2-quick-start/sunset.jpg
    
    BUCKET developer-b2-quick-start CONTAINS 14 OBJECTS
    
    Process finished with exit code 0

    Try pasting one of the jpg URLs into your browser. Your browser will show the image, since Backblaze B2 returns objects in public buckets via an unsigned HTTPS request.

    This concludes our review of the sample application's function list_objects_browsable_url() and the logic in the conditional block in the sample application's main() function that both calls it and then uses print() statements to output the values returned.

    For now, you can explore the remainder of this code on your own. We will publish more lessons in the future.

    Have a request or idea for the Backblaze S3-Compatible API ? Please feel free to contact us at [email protected].


    Was this article helpful?