<commit_before>component
	output = false
	hint = "I provide methods for creating signed web proxy URLs for the ImgIX API."
	{

	/**
	* I generate signed web proxy URLs for a source represented by the source domain
	* and secret token.
	* 
	* @newDomain I am the source domain (including the protocol) for the web proxy.
	* @newToken I am the secret token associated with the source.
	* @output false
	*/
	public any function init(
		required string newDomain,
		required string newToken
		) {

		// Store the properties for all subsequent URLs.
		domain = newDomain;
		token = newToken;

		return( this );

	}


	// ---
	// PUBLIC METHODS.
	// ---


	/**
	* I build the ImgIX web proxy URL based on the given target URL and API commands.
	* 
	* @targetUrl I am the URL that ImgIX will request as the "origin" URL.
	* @commands I am a struct OR a string of key-value API commands.
	*/
	public string function getWebProxyUrl(
		required string targetUrl,
		required any commands
		) {

		var encodedTargetUrl = urlEncodeComponent( targetUrl );

		var normalizedCommands = normalizeCommands( commands );

		var stringToSign = "#token#/#encodedTargetUrl#?#normalizedCommands#";

		var signature = lcase( hash( stringToSign ) );

		return( domain & "/" & encodedTargetUrl & "?" & normalizedCommands & "&s=" & signature );

	}


	// ---
	// PRIVATE METHODS.
	// ---


	/**
	* I normalize the ImgIX API commands as a string. If the input is a string, it is
	* simply returned. If it is a struct, it is flattened into an amphersand delimited list.
	* 
	* @commands I am a string or struct of name-value pairs.
	* @output false
	*/
	private string function normalizeCommands( required any commands ) {

		if ( isSimpleValue( commands ) ) {

			return( commands );

		}

		if ( ! isStruct( commands ) ) {

			throw( 
				type = "ImgIX.InvalidArgument", 
				message = "The commands must either be a string or a struct."
			);

		}

		var pairs = [];

		for ( var command in commands ) {

			var name = lcase( command );
			var value = urlEncodeComponent( commands[ command ] );

			arrayAppend( pairs, "#name#=#value#" );

		}

		return( arrayToList( pairs, "&" ) );

	}


	/**
	* I encode the given URL for use as the "path" portion of the ImgIX web proxy url.
	* 
	* @targetUrl I am the full URL (including protocol, excluding ImgIX commands).
	* @output false
	*/
	private string function urlEncodeComponent( required string targetUrl ) {

		targetUrl = urlEncodedFormat( targetUrl, "utf-8" );

		// At this point, we have a key that has been encoded too aggressively by
		// ColdFusion. Now, we have to go through and un-escape the characters that
		// will mess up the signature.

		// The following are "unreserved" characters in the RFC 3986 spec for Uniform
		// Resource Identifiers (URIs) - http://tools.ietf.org/html/rfc3986#section-2.3
		targetUrl = replace( targetUrl, "%2E", ".", "all" );
		targetUrl = replace( targetUrl, "%2D", "-", "all" );
		targetUrl = replace( targetUrl, "%5F", "_", "all" );
		targetUrl = replace( targetUrl, "%7E", "~", "all" );

		// Technically, the "/" characters can be encoded and will work. However, I just 
		// don't like the way the URL looks with nothing but escaped path markers. This 
		// one is just for personal preference.
		targetUrl = replace( targetUrl, "%2F", "/", "all" );

		// This one isn't necessary; but, I think it makes for a more attractive URL.
		targetUrl = replace( targetUrl, "%20", "+", "all" );

		return( targetUrl );

	}

}<commit_msg>Fix verbiage used in encoding method.<commit_after>component
	output = false
	hint = "I provide methods for creating signed web proxy URLs for the ImgIX API."
	{

	/**
	* I generate signed web proxy URLs for a source represented by the source domain
	* and secret token.
	* 
	* @newDomain I am the source domain (including the protocol) for the web proxy.
	* @newToken I am the secret token associated with the source.
	* @output false
	*/
	public any function init(
		required string newDomain,
		required string newToken
		) {

		// Store the properties for all subsequent URLs.
		domain = newDomain;
		token = newToken;

		return( this );

	}


	// ---
	// PUBLIC METHODS.
	// ---


	/**
	* I build the ImgIX web proxy URL based on the given target URL and API commands.
	* 
	* @targetUrl I am the URL that ImgIX will request as the "origin" URL.
	* @commands I am a struct OR a string of key-value API commands.
	*/
	public string function getWebProxyUrl(
		required string targetUrl,
		required any commands
		) {

		var encodedTargetUrl = urlEncodeComponent( targetUrl );

		var normalizedCommands = normalizeCommands( commands );

		var stringToSign = "#token#/#encodedTargetUrl#?#normalizedCommands#";

		var signature = lcase( hash( stringToSign ) );

		return( domain & "/" & encodedTargetUrl & "?" & normalizedCommands & "&s=" & signature );

	}


	// ---
	// PRIVATE METHODS.
	// ---


	/**
	* I normalize the ImgIX API commands as a string. If the input is a string, it is
	* simply returned. If it is a struct, it is flattened into an amphersand delimited list.
	* 
	* @commands I am a string or struct of name-value pairs.
	* @output false
	*/
	private string function normalizeCommands( required any commands ) {

		if ( isSimpleValue( commands ) ) {

			return( commands );

		}

		if ( ! isStruct( commands ) ) {

			throw( 
				type = "ImgIX.InvalidArgument", 
				message = "The commands must either be a string or a struct."
			);

		}

		var pairs = [];

		for ( var command in commands ) {

			var name = lcase( command );
			var value = urlEncodeComponent( commands[ command ] );

			arrayAppend( pairs, "#name#=#value#" );

		}

		return( arrayToList( pairs, "&" ) );

	}


	/**
	* I encode the given URL for use as the "path" portion of the ImgIX web proxy url.
	* 
	* @urlComponent I am the URL component that needs to be encoded.
	* @output false
	*/
	private string function urlEncodeComponent( required string urlComponent ) {

		urlComponent = urlEncodedFormat( urlComponent, "utf-8" );

		// At this point, we have a key that has been encoded too aggressively by
		// ColdFusion. Now, we have to go through and un-escape the characters that
		// will mess up the signature.

		// The following are "unreserved" characters in the RFC 3986 spec for Uniform
		// Resource Identifiers (URIs) - http://tools.ietf.org/html/rfc3986#section-2.3
		urlComponent = replace( urlComponent, "%2E", ".", "all" );
		urlComponent = replace( urlComponent, "%2D", "-", "all" );
		urlComponent = replace( urlComponent, "%5F", "_", "all" );
		urlComponent = replace( urlComponent, "%7E", "~", "all" );

		// Technically, the "/" characters can be encoded and will work. However, I just 
		// don't like the way the URL looks with nothing but escaped path markers. This 
		// one is just for personal preference.
		urlComponent = replace( urlComponent, "%2F", "/", "all" );

		// This one isn't necessary; but, I think it makes for a more attractive URL.
		urlComponent = replace( urlComponent, "%20", "+", "all" );

		return( urlComponent );

	}

}
{'fraction_non_alphanumeric': 0.11274787535410764, 'fraction_numerical': 0.0050991501416430595, 'mean_word_length': 3.141348973607038, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1962788', 'n_tokens_mistral': 2339, 'n_tokens_neox': 2070, 'n_words': 845}