The use case is a user/client sends a request to a server running PHP. I am trying to write the PHP code on the server e.g. an API endpoint to process the request.
I have existing production PHP code that extracts a JSON web token (in the form of a string) from a JSON request where the content-type specified in the request from the client is application/json
. The following code extracts the string using php://input
which works as long as the content-type of the request is application/json
.
$jsonString = file_get_contents('php://input');
$jsonArray = json_decode($jsonString, true);
$jwt =$jsonArray['jwt'];
var_dump($jwt); //THIS IS FOR DEBUGGING. COMMENTED OUT IN PRODUCTION
It returns the following string:
string(414) "hlMox0-LOTS OF CHARACTERS-za2b"
Please note the prefix string(414)
is added by var_dump
. If I merely echo the variable $jwt
, it displays the string by itself without that prefix.
This JSON web token string can be successfully decoded to authenticate user.
I now need to write the code for another endpoint for client requests that enable the client to send an image file and metadata. In this case, to support file transfer, the user/client must specify content-type
multipart/form-data
in the request. However, php/input
does not work with multipart data and the only way to retrieve the meta data is from the $_POST
variable. In this case the resulting string when extracted and displayed with var_dump()
is designated by var_dump
as optional.
$jwt = $_POST['jwt'];
var_dump($jwt);
This yields:
"Optional(414)("hlMox0-LOTS OF CHARACTERS-za2b")";
Once again, var_dump
adds the prefix Optional(414)
. If I just echo the value, then it is identical to the string in the first case.
Although this string when echoed appears identical to the one above, I cannot decode this variable. Var_dump suggests that although the strings echo the same they are different. The second version is an "optional." For those not familiar with the term optional, it is used in many programming languages to designate a variable that explicitly can either have a nil value or not. Evidently, PHP recognizes this idea with the var_dump
function. However, I cannot find anything that expands on this in the documentation.
Why would a string accessed through the $_POST
variable be different than one accessed through php://input
?
Insofar as var-dump is identifying a difference between optional and string, why would accessing the data through $_POST
yield an optional instead of a string?
Ultimately, how can I convert the $_POST['jwt']
obtained from $_POST
to an ordinary string. What could be wrong with it?
Swift optionals are used where a value may be absent.
An optional can be unwrapped to produce the wrapped value, if there is one.
In your Swift code you are using string(forKey:)
to obtain the JWT from User Defaults (As an aside, UserDefaults
isn't a very secure place to store a token; The Keychain is a better choice).
string(forKey:)
returns an optional String because there may not be a value in UserDefaults
for the specified key.
When you access an optional in a String context, it returns "Optional value"`.
You are accessing your values in a String context because you are using string interpolation ("\(value)"
). This is because your dictionary elements are of type Any
.
Swift is a strongly typed language and wherever possible you should use specific types, rather than Any
. If your dictionary was [String:String]
, for example, you would have received a compiler warning when you tried to store ajwt
in the dictionary, because a String?
(Optional String) is not a String
- Strong typing catches errors at compile time.
If your values aren't all strings you need to keep the dictionary as [String:Any]
.
Either way, you need to unwrap the optional. The best way to do this is with a conditional let in a guard
statement:
if let ajwt = UserDefaults.standard.string(forKey: "ajwt") else {
// Report some error because there is no JWT available
print("No JWT")
return
}
let parameters: [String:Any] = ["query":query, "jwt":ajwt,"id":id]
...
Now, ajwt
will be a String
because you have conditionally unwrapped, printing an error and returning early if the jwt is not available. Your function could also throw
an error in this case.