mirror of
				https://github.com/avitex/elixir-vultr
				synced 2025-10-31 14:13:28 +00:00 
			
		
		
		
	Improve request implementation and return format
This commit is contained in:
		
							parent
							
								
									216a9dec8f
								
							
						
					
					
						commit
						8279a50c92
					
				| @ -1,6 +1,6 @@ | |||||||
| language: elixir | language: elixir | ||||||
| elixir: | elixir: | ||||||
|   - 1.4.0 |   - 1.5.0 | ||||||
| notifications: | notifications: | ||||||
|   recipients: |   recipients: | ||||||
|     - theavitex@gmail.com |     - theavitex@gmail.com | ||||||
|  | |||||||
							
								
								
									
										16
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										16
									
								
								README.md
									
									
									
									
									
								
							| @ -1,5 +1,5 @@ | |||||||
| [](https://travis-ci.org/avitex/elixir-vultr) | [](https://travis-ci.org/avitex/elixir-vultr) | ||||||
| [](https://hexdocs.pm/vultr) | [](https://hex.pm/packages/vultr) | ||||||
| [](https://hexdocs.pm/vultr) | [](https://hexdocs.pm/vultr) | ||||||
| 
 | 
 | ||||||
| # Vultr | # Vultr | ||||||
| @ -13,7 +13,7 @@ Documentation hosted on [hexdocs](https://hexdocs.pm/vultr). | |||||||
| 
 | 
 | ||||||
|   ```elixir |   ```elixir | ||||||
|   def deps do |   def deps do | ||||||
|     [{:vultr, "~> 0.1.0"}] |     [{:vultr, "~> 0.2.0"}] | ||||||
|   end |   end | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
| @ -24,20 +24,12 @@ Documentation hosted on [hexdocs](https://hexdocs.pm/vultr). | |||||||
|   Vultr.app_list() |   Vultr.app_list() | ||||||
| 
 | 
 | ||||||
|   # Example response |   # Example response | ||||||
|   %{ |   {:ok, %{ "1" => %{"APPID" => "1", "deploy_name" => "LEMP on CentOS 6 x64", ... }, ... }} | ||||||
|     body: %{ "1" => %{"APPID" => "1", "deploy_name" => "LEMP on CentOS 6 x64", ... }, ... }, |  | ||||||
|     headers: %{ "content-type" => "application/json", ... }, |  | ||||||
|     method: :get, |  | ||||||
|     opts: [], |  | ||||||
|     query: [], |  | ||||||
|     status: 200, |  | ||||||
|     url: "https://api.vultr.com/v1/app/list" |  | ||||||
|   } |  | ||||||
|   ``` |   ``` | ||||||
| 
 | 
 | ||||||
| #### Using authenticated methods | #### Using authenticated methods | ||||||
| 
 | 
 | ||||||
|   ```elixir |   ```elixir | ||||||
|   client = Vultr.client("<APIKEY>") |   client = Vultr.client("<APIKEY>") | ||||||
|   Vultr.server_list(client, %{}) |   Vultr.server_list(client, []) | ||||||
|   ``` |   ``` | ||||||
							
								
								
									
										127
									
								
								lib/request.ex
									
									
									
									
									
								
							
							
						
						
									
										127
									
								
								lib/request.ex
									
									
									
									
									
								
							| @ -1,6 +1,10 @@ | |||||||
| defmodule Vultr.Request do | defmodule Vultr.Request do | ||||||
|  | 	@moduledoc false | ||||||
| 
 | 
 | ||||||
| 	#@SPECIAL_PARAMS ["SUBID", "DCID", "RECORDID", "VPSPLANID", "APPID", "OSID", "ISOID", "SCRIPTID", "SNAPSHOTID", "SSHKEYID", "BACKUPID", "USERID"] | 	@special_params [ | ||||||
|  | 		:subid, :dcid, :recordid, :vpsplanid, :appid, :osid, | ||||||
|  | 		:isoid, :scriptid, :snapshotid, :sshkeyid, :backupid, :userid, | ||||||
|  | 	] | ||||||
| 
 | 
 | ||||||
| 	defmacro __using__(_) do | 	defmacro __using__(_) do | ||||||
| 		quote do | 		quote do | ||||||
| @ -15,55 +19,88 @@ defmodule Vultr.Request do | |||||||
| 		endpoint_required_access = Keyword.get(endpoint_opts, :required_access, nil) | 		endpoint_required_access = Keyword.get(endpoint_opts, :required_access, nil) | ||||||
| 		endpoint_has_params = (length(endpoint_params) > 0) | 		endpoint_has_params = (length(endpoint_params) > 0) | ||||||
| 
 | 
 | ||||||
| 		request_client_var = Macro.var(:client, nil) | 		common_args = [__CALLER__.module, endpoint_method, endpoint_path] | ||||||
| 		request_params_var = Macro.var(:params, nil) |  | ||||||
| 
 | 
 | ||||||
| 		function_args = | 		func = &__MODULE__.perform_request/5 | ||||||
|  | 
 | ||||||
|  | 		func_name = | ||||||
|  | 			endpoint_path | ||||||
|  | 			|> String.replace("/", "_") | ||||||
|  | 			|> String.to_atom | ||||||
|  | 
 | ||||||
|  | 		func_doc = gen_doc( | ||||||
|  | 			endpoint_method, endpoint_path,  | ||||||
|  | 			endpoint_description, endpoint_params,  | ||||||
|  | 			endpoint_required_access, endpoint_requires_api_key | ||||||
|  | 		) | ||||||
|  | 
 | ||||||
|  | 		func_body = | ||||||
| 			cond do | 			cond do | ||||||
| 				endpoint_requires_api_key && endpoint_has_params -> | 				endpoint_requires_api_key && endpoint_has_params -> | ||||||
| 					[request_client_var, request_params_var] | 					quote do | ||||||
|  | 						def unquote(func_name)(client, params \\ []) when is_list(params) do | ||||||
|  | 							unquote(func).(unquote_splicing(common_args), client, params) | ||||||
|  | 						end | ||||||
|  | 					end | ||||||
| 				endpoint_requires_api_key -> | 				endpoint_requires_api_key -> | ||||||
| 					[request_client_var] | 					quote do | ||||||
|  | 						def unquote(func_name)(client) do | ||||||
|  | 							unquote(func).(unquote_splicing(common_args), client, []) | ||||||
|  | 						end | ||||||
|  | 					end | ||||||
| 				endpoint_has_params -> | 				endpoint_has_params -> | ||||||
| 					[request_params_var] | 					quote do | ||||||
|  | 						def unquote(func_name)(params \\ []) when is_list(params) do | ||||||
|  | 							unquote(func).(unquote_splicing(common_args), nil, params) | ||||||
|  | 						end | ||||||
|  | 					end | ||||||
| 				true -> | 				true -> | ||||||
| 					[] | 					quote do | ||||||
|  | 						def unquote(func_name)() do | ||||||
|  | 							unquote(func).(unquote_splicing(common_args), nil, []) | ||||||
| 						end | 						end | ||||||
| 
 |  | ||||||
| 		tesla_args = |  | ||||||
| 			if endpoint_requires_api_key do |  | ||||||
| 				[request_client_var] |  | ||||||
| 			else |  | ||||||
| 				[] |  | ||||||
| 					end | 					end | ||||||
| 
 |  | ||||||
| 		tesla_args = |  | ||||||
| 			if endpoint_method === :get && endpoint_has_params do |  | ||||||
| 				tesla_args ++ [quote do |  | ||||||
| 					unquote(endpoint_path) <> "?" <> URI.encode_query(unquote(request_params_var)) |  | ||||||
| 				end] |  | ||||||
| 			else |  | ||||||
| 				tesla_args ++ [quote do |  | ||||||
| 					unquote(endpoint_path) |  | ||||||
| 				end] |  | ||||||
| 			end |  | ||||||
| 		 |  | ||||||
| 		tesla_args = |  | ||||||
| 			if endpoint_method !== :get && endpoint_has_params do |  | ||||||
| 				tesla_args ++ [request_params_var] |  | ||||||
| 			else |  | ||||||
| 				tesla_args |  | ||||||
| 			end | 			end | ||||||
| 
 | 
 | ||||||
| 		quote do | 		quote do | ||||||
| 			@doc unquote(documentation(endpoint_method, endpoint_path, endpoint_description, endpoint_params, endpoint_required_access, endpoint_requires_api_key)) | 			@doc unquote(func_doc) | ||||||
| 			def unquote(function_name(endpoint_path))(unquote_splicing(function_args)) do | 			unquote(func_body) | ||||||
| 				unquote(endpoint_method)(unquote_splicing(tesla_args)) |  | ||||||
| 			end |  | ||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| 	defp function_name(path), do: path |> String.replace("/", "_") |> String.to_atom | 	def perform_request(caller, method, url, client, params) do | ||||||
|  | 		opts = [url: url, method: method] ++ prepare_params(method, params) | ||||||
|  | 		resp = Tesla.perform_request(caller, client, opts) | ||||||
|  | 		case resp.status do | ||||||
|  | 			200 -> {:ok, resp.body} | ||||||
|  | 			400 -> {:error, :invalid_api_location, resp.body} | ||||||
|  | 			403 -> {:error, :invalid_api_key, resp.body} | ||||||
|  | 			405 -> {:error, :invalid_http_method, resp.body} | ||||||
|  | 			412 -> {:error, :bad_request, resp.body} | ||||||
|  | 			500 -> {:error, :server_error, resp.body} | ||||||
|  | 			503 -> {:error, :rate_limit, resp.body} | ||||||
|  | 		end | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
|  | 	defp prepare_params(:get, nil), do: [query: []] | ||||||
|  | 	defp prepare_params(_, nil), do: [body: %{}] | ||||||
|  | 	defp prepare_params(:get, params), do: [query: capitalize_special_params(params)] | ||||||
|  | 	defp prepare_params(_, params), do: [body: Enum.into(capitalize_special_params(params), %{})] | ||||||
|  | 
 | ||||||
|  | 	defp capitalize_special_params(params) do | ||||||
|  | 		Enum.map(params, fn {k, v} -> | ||||||
|  | 			is_special_param = | ||||||
|  | 				Enum.any?(@special_params, fn special_param -> | ||||||
|  | 					special_param == k | ||||||
|  | 				end) | ||||||
|  | 
 | ||||||
|  | 			if is_special_param do | ||||||
|  | 				{String.upcase(k), v} | ||||||
|  | 			else | ||||||
|  | 				{k, v} | ||||||
|  | 			end | ||||||
|  | 		end) | ||||||
|  | 	end | ||||||
| 
 | 
 | ||||||
| 	defp normalize_param({name, opts}) do | 	defp normalize_param({name, opts}) do | ||||||
| 		type = Keyword.fetch!(opts, :type) | 		type = Keyword.fetch!(opts, :type) | ||||||
| @ -84,7 +121,7 @@ defmodule Vultr.Request do | |||||||
| 	################################################## | 	################################################## | ||||||
| 	# Documentation helpers | 	# Documentation helpers | ||||||
| 
 | 
 | ||||||
| 	defp documentation(method, path, desc, params, required_access, api_key) do | 	defp gen_doc(method, path, desc, params, required_access, api_key) do | ||||||
| 		doc = """ | 		doc = """ | ||||||
| 		#{desc} | 		#{desc} | ||||||
| 		""" | 		""" | ||||||
| @ -130,14 +167,6 @@ defmodule Vultr.Request do | |||||||
| 		end | 		end | ||||||
| 	end | 	end | ||||||
| 
 | 
 | ||||||
| 	defp doc_api_key(nil), do: "No" |  | ||||||
| 	defp doc_api_key(atm), do: atom_to_word(atm) |  | ||||||
| 
 |  | ||||||
| 	defp doc_required_access(nil), do: "None" |  | ||||||
| 	defp doc_required_access(atm), do: Atom.to_string(atm) |  | ||||||
| 	 |  | ||||||
| 	defp atom_to_word(atm), do: atm |> Atom.to_string |> String.capitalize |  | ||||||
| 
 |  | ||||||
| 	defp doc_method(method) do | 	defp doc_method(method) do | ||||||
| 		if !Enum.any?([:get, :post], fn supported -> method == supported end) do | 		if !Enum.any?([:get, :post], fn supported -> method == supported end) do | ||||||
| 			raise ArgumentError, message: "Bad method" | 			raise ArgumentError, message: "Bad method" | ||||||
| @ -145,4 +174,12 @@ defmodule Vultr.Request do | |||||||
| 
 | 
 | ||||||
| 		method |> Atom.to_string |> String.upcase() | 		method |> Atom.to_string |> String.upcase() | ||||||
| 	end | 	end | ||||||
|  | 
 | ||||||
|  | 	defp doc_api_key(nil), do: "No" | ||||||
|  | 	defp doc_api_key(atm), do: atom_to_word(atm) | ||||||
|  | 
 | ||||||
|  | 	defp doc_required_access(nil), do: "None" | ||||||
|  | 	defp doc_required_access(atm), do: Atom.to_string(atm) | ||||||
|  | 
 | ||||||
|  | 	defp atom_to_word(atm), do: atm |> Atom.to_string |> String.capitalize | ||||||
| end | end | ||||||
| @ -8,6 +8,9 @@ defmodule Vultr do | |||||||
| 
 | 
 | ||||||
| 	adapter :ibrowse | 	adapter :ibrowse | ||||||
| 
 | 
 | ||||||
|  | 	@doc """ | ||||||
|  | 	Create a Vultr client with an API-Key for authenticated methods | ||||||
|  | 	""" | ||||||
| 	def client(api_key) do | 	def client(api_key) do | ||||||
| 		Tesla.build_client [ | 		Tesla.build_client [ | ||||||
| 			{Tesla.Middleware.Headers, %{ "API-Key" => api_key }} | 			{Tesla.Middleware.Headers, %{ "API-Key" => api_key }} | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								mix.exs
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								mix.exs
									
									
									
									
									
								
							| @ -8,7 +8,7 @@ defmodule Vultr.Mixfile do | |||||||
| 	def project do | 	def project do | ||||||
| 		[ | 		[ | ||||||
| 			app: :vultr, | 			app: :vultr, | ||||||
| 			version: "0.1.0", | 			version: "0.2.0", | ||||||
| 			elixir: "~> 1.3", | 			elixir: "~> 1.3", | ||||||
| 			deps: deps(), | 			deps: deps(), | ||||||
| 			description: @description, | 			description: @description, | ||||||
| @ -25,7 +25,7 @@ defmodule Vultr.Mixfile do | |||||||
| 		[ | 		[ | ||||||
| 			{:inch_ex, "~> 0.5", only: :dev}, | 			{:inch_ex, "~> 0.5", only: :dev}, | ||||||
| 			{:ex_doc, "~> 0.14", only: :dev, runtime: false}, | 			{:ex_doc, "~> 0.14", only: :dev, runtime: false}, | ||||||
| 			{:tesla, "~> 0.7.0"}, | 			{:tesla, "~> 0.7.1"}, | ||||||
| 			{:ibrowse, "~> 4.2"}, | 			{:ibrowse, "~> 4.2"}, | ||||||
| 			{:poison, ">= 1.0.0"} | 			{:poison, ">= 1.0.0"} | ||||||
| 		] | 		] | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user