   @spec jsonp(Plug.Conn.t, term, Keyword.t) :: Plug.Conn.t
   def jsonp(conn, data, opts \\ []) do
     callback_param = Keyword.get(opts, :callback, "callback")
-    callback = Dict.get(conn.query_params, callback_param)
-
-    if callback && String.length(callback) > 0 do
+    callback = Dict.get(conn.query_params, callback_param, "")
+
+    if callback != "" do
+      validate_jsonp_callback!(callback)
+
       encoder = get_json_encoder()
-
-      allowed_chars = [?0..?9, ?A..?Z, ?a..?z, [?_]]
-      |> Enum.map(&Enum.to_list/1)
-      |> List.flatten()
-
-      callback_valid = callback
-      |> String.to_char_list()
-      |> Enum.all?(&(&1 in allowed_chars))
-
-      callback_valid || raise ArgumentError, "the callback name contains invalid characters"
 
       body = encoder.encode_to_iodata!(data) 
       |> IO.iodata_to_binary()
 
       body = body
-      |> String.replace(<< 0x2028 :: utf8 >>, "\\u2028")
-      |> String.replace(<< 0x2029 :: utf8 >>, "\\u2029")
+      |> String.replace(<<0x2028::utf8>>, "\\u2028")
+      |> String.replace(<<0x2029::utf8>>, "\\u2029")
       
       body = "/**/ typeof " <> callback <> " === 'function' && " <> callback <> "(" <> body <> ");"
 

      json conn, data
    end
  end

  @doc """
  Sends text response.

  overridden with the `:callback` option and is expected to be a 
  string.

  Only alphanumeric characters and underscore are allowed in the
  callback name. Otherwise an exception is raised.

  ## Examples
