Lukas Z's Blog

How to Redirect HTTP and HTTPS Requests Using Namecheap and AWS

This is a mini writeup for a very specific case.

Let’s say we have a domain name, ourcooldoma.in. And for some reason we want to redirect all traffic to somecool.org. And the following things also apply:

  • ourcooldoma.in is registered at a hoster like Namecheap.
  • somecool.org does not belong ot us at all.
  • we want to redirect ourcooldoma.in and www.ourcooldoma.in.
  • we are already using AWS.

(Told you it was specific..)

Then we can do this:

  1. Set up an empty S3 bucket at AWS and make it public.
  2. In the properties of the bucket use the Static Website Hosting feature in Properties and define a redirect to somecool.org. Take note of the Endpoint value in the Static Website Hosting box.
  3. Because we support HTTPS use ACM to create a certificate that matches ourcooldoma.in and www.ourcooldoma.in (or *.ourcooldoma.in).
  4. Create a Cloudfront distribution that uses that bucket’s Endpoint as origin and is valid for the domains www.ourcooldoma.in and ourcooldoma.in. Use the certificate from the step before.
  5. Configure ALIAS records at Namecheap for www and @ pointing to the domain name of our Cloudfront distribution.

Done!

Now every request to ourcooldoma.in will result in a DNS query that returns the ALIAS entry (though I believe ALIAS is not a standard key but a technicality provided by Namecheap and others to circumvent the restriction of CNAME, which one would normally use, but which cannot be used with @ unless you are ok with masking your MX and other subdomain records).

So our request will be actually fired against the IP address at Cloudfront but the client still expects a valid SSL certificate for ourcooldoma.in. Cloudfront provides that (created in step 3) and we can finally get to the (cached) bucket, which only does one thing: 301 redirect the client to somecool.org.

How to Include Binary Vendor Frameworks in Xcode With and Without Cocoapods

Sometimes we have a closed source binary library that we want to include in our iOS project. To do that Xcode needs to do the following things:

  • Find the framework (via defaults or the Framework Search Paths setting).
  • Embed the framework in the bundle and sign it.
  • Link against the framework during build.
  • Strip any architectures from the framework binary that are not required (or even forbidden: You cannot for instance ship a binary that contains code for x86_64 through AppStoreConnect).

I want to add another complication, which is of course optional: The framework is only included for some configurations, for example DebugWithFramework. It should not be included in all other configs.

First I will show how to do it manually and then I will show the Cocoapods way, which, in my humble developer opinion, is superior.

Approach 1: The manual approach

So let’s say we want to do the above steps manually.

For the optional “only some configurations” requirement make sure the configurations have been created.

Step 1: Add the Framework

We can just pull the binary framework into our file tree in Xcode and we’re done. However, if we only want to include it in some configurations we should uncheck the target membership of the framework and add it manually.

Step 2: Framework Search Paths & Linker Setting

We need to tell our build system about our Framework. I believe this is already done for us if we add the Framework to our target and/or if we drag the Framework into the “Embedded Frameworks” box in settings.

But this part of the post is about the manual approach, with inclusion for only certain configurations, so we need to do two things: Set the Framework Search Path and tell the Linker.

But this is easy:

In Build Settings look for Other Linker Flags and add two lines for the configurations that matter (you may need to click the drop down arrow first): “-framework” and “CoolFramework” if “CoolFramework” is the name of your framework, otherwise please substitute the correct value.

Finally in Build Settings look for Framework Search Paths. Again select the configurations that you care about and add a new line below $(inherited) that looks something like this:


$(PROJECT_DIR)/Frameworks/MyCoolFramework/debug

And you should be good to go.

At this point your app probably compiles but at runtime it crashes complaining that it can’t find the Framework.

That’s because it’s not in the Bundle yet. For that you need the next step:

Step 3: Embed & Sign

If it’s supposed to be included for all configs we can just add it by dragging it into the Embedded Frameworks box in our project settings (assuming it’s not already there). Then make sure the option is set to “Embed & Sign” and you’re done.

It gets slightly more complicated if we include it manually. For that we can add a custom script build phase in our Build Phases tab that looks somewhat like this:


if [[ -z ${SCRIPT_INPUT_FILE_0} || -z ${SCRIPT_OUTPUT_FILE_0} ]]; then
    echo "This Xcode Run Script build phase must be configured with Input & Output Files"
    exit 1
fi

echo "Embed ${SCRIPT_INPUT_FILE_0}"
if [[ $CONFIGURATION == 'DebugWithFramework' || $CONFIGURATION == 'ReleaseWithFramework' ]]; then
      FRAMEWORK_SOURCE=${SCRIPT_INPUT_FILE_0}
        FRAMEWORK_DESTINATION=${SCRIPT_OUTPUT_FILE_0}
        DESTINATION_FOLDER=`dirname ${FRAMEWORK_DESTINATION}`
        
        mkdir -p ${DESTINATION_FOLDER}
        cp -Rv ${FRAMEWORK_SOURCE} ${FRAMEWORK_DESTINATION}

        CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
        if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
            CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
        fi

        BINARY_NAME=`basename ${FRAMEWORK_DESTINATION} .framework`
        codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" ${FRAMEWORK_DESTINATION}/${BINARY_NAME}
        echo " ✅ Embedded successfully"
    else
        echo " ❌ Non MyCoolFramework build detected - do not embed"
    fi

Script phases have input and output files (extra input text fields), and in our case we can set it to the following values:


$(SOURCE_ROOT)/Frameworks/MyCoolFramework/debug/MyCoolFramework.framework

for the Input and


${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MyCoolFramework.framework

for the output.

So the output specifies where the binary goes in the compiled bundle.

Disclaimer: This code is a slightly modified snippet from Github. If I find it, I’ll link to it later.

Step 4: Strip Unnecessary Architectures

The app may run fine now in your Simulator or even on an actual iPhone or iPad, but if we want to submit our app to the AppStore we need to do one more thing: Remove architectures that are not used by the target devices.

Quick sidenote: What are architectures?

Well if you write source code it eventually gets compiled into machine code. Zeroes and Ones that are actually instructions (opcodes + arguments) for the CPU. But CPUs are different, they have different architectures and each architecture has different opcodes. (Simply speaking.) Until Apple switches to Apple Silicon, your mac (and your iOS Simulator) most likely has a x86_64 Intel CPU. And your iPhone most likely has a armv7 CPU.

If you have a binary framework that you did not compile yourself it must have the binary code for correct architectures already included. And the best case is that it has the code for _all_required architectures.

So what do we do before uploading to the AppStore?

We get rid off all binary code that is not for iPhone and iPad.

And we do it using a command line tool called lipo.

Now remember, Xcode does all this for you automatically, usually, but we are handling a custom case here where our framwork is binary.

Here’s the build script phase for that:


if [[ $CONFIGURATION == 'DebugWithFramework' || $CONFIGURATION == 'ReleaseWithFramework' ]]; then

  FRAMEWORK="MyCoolFramework"
  FRAMEWORK_EXECUTABLE_PATH="${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}/$FRAMEWORK.framework/$FRAMEWORK"
  EXTRACTED_ARCHS=()

  for ARCH in $ARCHS
  do
    lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
    EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
  done

  lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
  
  rm "${EXTRACTED_ARCHS[@]}"
  rm "$FRAMEWORK_EXECUTABLE_PATH"
  mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
fi

This can be changed a bit to work for all frameworks I guess, but here it’s the special case in which we have one framework, MyCoolFramework, and two configurations DebugWithFramework and ReleaseWithFramework.

Step 5: Using the Framework in our code

Just briefly I want to mention how you can prevent compilation errors by using an #if clause in your code. Consider this Swift code:


#if canImport(MyCoolFramework)
import MyCoolFramework
#endif

You can use these if-blocks liberally everywhere in your Swift code.

Conclusion & Open Questions

I think we’re done. (If not please write a comment so I can fix it. I don’t have a lot of time to double check everything I’ve written here. Thanks.)

As you can see the manual approach is tiresome but at least we learn somehting about how Xcode builds apps for us!

I want to mention one more complication that can and probably will occur: What if our Framework has dependencies, for example Cocapods that must be present? They can be added in the Podfile but if we need to restrict the inclusion to certain configurations then we must take extra steps.

That’s why we should use Cocoapods all the way in the first place! ;)

Ok let’s look at how that’s done in the second part.

Approach 2: Using Cocapods

Now we will make our own Cocoapod that simply includes our vendor framework. Now why do we want to do that? Because Cocoapods takes care of all the steps above for us!

That’s right, the batteries are included. Let’s start.

Btw. I assume you are already using Cocoapods and your project already has a Podfile. (If not, please add Cocoapods now and run pod init in your project folder.)

Step 1: Writing a gemspec file

A pod is defined by a gemspec file that instructs the pod binary what to do when installing. I’ll keep it brief and just paste you own for our case. But there are more options which may be required. Especially if you are also having swift and objective c files in there somewhere that must be compiled. Our case is actually simpler because the framework is binary.

We’re writing a local pod by the way. You could have it remotely in some git repo and you could even publish it in the cococapods repository but our case here it’s local only and it’s in the same git repository as our app. It’s basically just in a subfolder.

Here we go:


Pod::Spec.new do |spec|
  spec.name         = "MyCoolFramework"
  spec.version      = "0.0.1"
  spec.summary      = "Podspec wrapper for the MyCoolFramework framework."
  spec.authors      = { "Lukas Zielinski" => "http://www.lukaszielinski.de" }
  spec.homepage     = "http://www.lukaszielinski.de"
  spec.platform     = :ios, "12.0"
  spec.source       = { :http => 'file://' + __dir__ + '/MyCoolFramework.framework.zip' }
  spec.public_header_files = "MyCoolFramework.framework/Headers/*.h"
  spec.ios.vendored_frameworks = "MyCoolFramework.framework"

  spec.dependency 'RxSwift', '5.1.0'
  spec.dependency 'RxCocoa', '5.1.0'
  spec.dependency 'RxDataSources', '4.0.1'
end

The gemspec should be in the same folder as they framework and the framework folder should be zipped. Cocoapods will unzip the archive during installation.

There’s also a speciality here: Our framework has dependencies, it requires the RxSwift pod to run. I’ve added this to show you to demonstrate that it’s easy to add dependencies now and also to show a peculiarity about Cocoapods below.

Step 2: Adding our brand new pod

Let’s see how our Podfile looks now:


target 'App' do
  pod "MyCoolFramework", :podspec => "Frameworks/MyCoolFramework/debug/", :configurations => ["DebugWithFramework, "ReleaseWithFramework"]

  pod "RxCocoa", "5.1.0", :configurations => ["DebugWithFramework, "ReleaseWithFramework"]
  pod "RxDataSources", "4.0.1", :configurations => ["DebugWithFramework, "ReleaseWithFramework"]
  pod "RxSwift", "5.1.0", :configurations => ["DebugWithFramework, "ReleaseWithFramework"]
  # explicit dependency for RxCocoa:
  pod 'RxRelay', '~> 5.0', :configurations => ["DebugWithFramework, "ReleaseWithFramework"]
end

And if we don’t care about configurations it’s just this:


target 'App' do
  pod "MyCoolFramework", :podspec => "Frameworks/MyCoolFramework/debug/"
end

Now we can run pod install and we’re good to go! We can run the app and even submit it to the AppStore, because Cocoapods takes care of all the steps from the manual approach for us!

There’s one thing that you should look out for regarding the configurations. As you see in the Podfile examples, it gets much more verbose when we want to restrict the pod to be included in certain configurations only. That is because Cocoapods requires us to also specify all the dependencies and the dependencies’ dependencies (transitive dependencies) explicitely IF we want to restrict them to some configurations.

Consider this:


target 'App' do
  pod "MyCoolFramework", :podspec => "Frameworks/MyCoolFramework/debug/", :configurations => ["DebugWithFramework, "ReleaseWithFramework"]
end

Here our framework is not included in the “Debug” stage, however it’s dependencies are. This is something to look out for.

Protip: Build and afterwards look inside your compiled app’s package. There’s a frameworks folder there. You should only see pods that are dependencies of our framework in apps build with those configurations.

Final words

That’s it, I hope this helps someone. Please send me any corrections or comment below. Thank you!

New Blog

I have decided to stop posting non work related content here after all. I think it could send a confusing message. After all I am a freelacne software professional and posting about storytelling might put prospect clients off.

For now, you can find “the blog where I randomly ramble about stuff” here.

Story Ideas 1

I write here to get better at writing, but let me also train my creativity muscle for fun.

In any case the Stephen King book which I’ve read recently has inspired me to come up with story ideas.

Maybe what I will type in a few seconds will be really bad, but hey, this is just a quick blog post. The fun part is that I will just start writing the first sentence and then, hopefully, the rest of the idea will write itself.

Let’s try.

Here we go:

The elected president of Ireland is fed up with superstition. He and his party ban all folklore from the school curriculum. As a matter of fact, a new law is passed: If you talk about elves and Leprechauns and so forth in public places such as bars or on Youtube, you can be fined up to 200 euros. Some however won’t have it. They rely on their folklore to sell their merchandise to tourists. So they come up with guerilla tactics that bring back the folklore into the mainstream. So they sabotage public holidays, paint fantasy graffiti and so on. They also uncover something very troubling about this president. He is not a human but an actual Leprechaun. So they are real after all! However, in order to survive the fantasy creatures need humans to forget about them. After this is discovered by the souvenir guerilla activits they face a choice to follow their profits or to protect the actual magical people. They split in two, a very angry leader decides to wipe them out once and for all, so he can forever sell the souvenirs. But through some magic and with the help of some children and a drunk (sorry for the clishee) old storyteller they manage to defeat him somehow. In the end the 21st century begins, everyone is a mobile phone zombie, constantly staring at Instagram and Tik Tok, but it is good. The fairtale creatures can at least live in peace for now.

Ok this has two weaknesses. One: I know nothing about Irish folklore and should definitely research before writing such a story. Also the alcohol clishee is bad. As a matter of fact, if I made such a story I would actually have no one drink in it at all. Secondly, it misses the explanation why the fairytale creatures want to be forgotten.

And where do the children and that old storytelling guy come from?

So many questions. But at least it’s a start.

Anyway, this is fun. I really just started with the first sentence and the rest wrote itself. I’ll do that more often to relax. Fun times. ☘️

It’s Not for You

You don’t like my blog? No problem, it’s not for you.

If it were, you would like it. At least some parts of it.

Seth Godin writes in one of his books that the spelling errors in Nigerian email scams serve a purpose. They filter out the smarter, arguably more difficult, readers. If you are put off by the spelling and the grammar you won’t reply to the email. Good, they don’t want you to. Because you most probably will be wasting their time. Others will be better victims. The Nigerian Prince email is not for you. [1]

And so it is with everything else.

Liberating, isn’t it? Suddenly we don’t need to make everyone happy with our art and our product. We can’t make everyone happy anyway, because different people have different preferences. But now we don’t have to feel so bad about it.

Another example: You approached a girl on the bus? And she rejected you harshley? That’s fine. You’re not for her.

Isn’t it useful to know that? To know it early?

Footnotes

[1] I doubt it’s always on purpose. I think some of that fraud spam is just 14 year old kids writing.

Our Surroundings

The place I live in, my car, my clothes, they all tell a story about me and it’s not random. What I am is reflected in my surroundings which are influenced by my preferences.

For instance there are some things I care less about. Other things irk me and I need to fix them. Maybe I need my car to be practical and maybe my clothes send out hints about my profession.

It’s all about harmony. This will sound a bit esoteric but I feel that we all have something surrounding us that is akin to a magnetic field.

(Or, just as valid: It’s just a little metaphor that we can employ to ramble about random things on our blogs.)

When we place a magnet on top of a surface with metal filings they will arrange in a certain way. In physics class, this is how teachers make the invisible magnetic fields visible.

In a similar way, if we put a person in a place and let some time pass, the place will be transformed according to the person.

For example, if a Zen monk from Japan moved into a German home, and he remained a Zen monk, the place would probably change for the better (I’m biased.). It’s a clishee but let’s say the house would be cleaner and the garden would appear very well looked after. At the same time he would be affected by his new life in Germany. Perhaps he would start eating bread or he would begin expressing his annoyance with German trains who are embarrasingly often late. So in reality it’s an interplay. It goes both ways.

The magnetic field doesn’t just affect things. It works with everything including people. We become more like the other humans we spend the most time with and they become more like us. The latter I believe is perhaps generally underrated. We may feel that we are drifting along and that the world is pulling us in a certain direction. That we are merely sentenced to react passively. But actually we too affect the others. By expressing ourselves we make an impression on other people and change their behavior, if ever so slightly. (We always do it regardless if it’s intentional.)

Perhaps a good example is when we become parents. The child is constantly exposed to our field and cannot help but absorb it. It’s the same with our friends. Just like the mental filings in physics class, we adjust. And they do, too. This creates a shared view of life and a sense of belonging.[1]

“Expressing ourselves” seems like such a new thing though. It’s probably more of an ideal of the west and rather foreign in the east. But no matter to which hemisphere we belong, there is some sort of mainstream culture, some great story that is shared by most. So in addition to all the smaller fields there are some bigger ones, shared between members of nations or regions of the earth.

And some shared by all humans.

The more time passes the more the differences between cultures will disappear. Despite a loss of influence by mainstream media the mainstream culture seems stronger than ever. For some reason. Maybe it’s some unifying power inherent in capitalism, which influences us all. Or it’s a fear of a loss of orientation after losing the mainstream narrative.

Perhaps, eventually, some really nice patterns will emerge between all the metal filings, the people, on this big surface we call Earth.

Let’s hope that there will be enough variety left.

Like someone once said: “Imagine the traffic jams if all people liked the same thing.”

Footnotes

[1] But what happens if someone changes? Will there be a force that is invested in keeping him the way he was? You bet.

What Precedes and Follows

Epictetus, a Stoic philosopher, says about our goals and dreams: “In every affair consider what precedes and follows, and then undertake it. Otherwise you will begin with spirit; but not having thought of the consequences, when some of them appear you will shamefully desist.”*

I suppose this is very good advice. Something that Jordan Peterson may say.

And yet, and yet.. how often have people succeeded at something because they overestimated their odds (and underestimated the difficulties)?

Perhaps luckily, they weren’t very imaginative and didn’t know what else to try. Perhaps they werent very impulsive, and their problems weren’t enough to trigger a flight reponse in them. Or they were just very stubborn. In any case, they sticked around. They tried some more and, eventually, everything worked out in their favor. And they got the treasure.

Sometimes what reads like disadvantages can be just what is required.

* = Link to a translation of the Enchiridion by Epictetus See paragraph 29 for the quote mentioned here.

Everyone Misunderstands the Mazda MX-5 Luggage Rack

I’m a big fan of the Mazda MX-5, which is also called Mazda Miata. I had one a few years ago and I still miss it. I think this is the perfect car. Unless you need a third seat or luggage space..

Speaking of luggage. What fascinates me is that virtually everyone installs the luggage rack the wrong way!

The only exception is the third gen Miata where it’s usually done right, and despite the fact that we all see the 3rd gen on the road most of us still don’t get it.

Here is what I mean:

Miata NB

The rack on this beautfiul 2nd gen should be rotated by 180 degrees. The short sticking out part should be towards the front, not back.

Why?

Because its function is to prevent your luggage from chopping your head off if you crash into something. It’s not there to prevent your luggage from falling down because of the crazy acceleration of the Miata.

Because, let’s face it, the Miata doesn’t accelerate that quickly.

3rd gen (“NC”) owners get it usually right, because the luggage racks are shipped with a brake light, since the rack obscures the 3rd brake lamp. So there’s just one way to install it, the correct way, the way that prevents your bags from killing you.

Or not just you. Everyone else that is unlucky enough to be crashed into by a Miata!

Just saying.

(Fanboy disclaimer: Luckily, this is a mostly theoretical discussion. The Miata handles awesomly. It’s rare that you would loose control and crash.)

But still.. I wonder, what else in life is obviously wrong, that we, the average people who never thought too much about it, don’t get?

Take It Away and Make Them Pay

I haven’t logged in to LinkedIn for years (or even a decade?) but today I actually wanted to contact someone who is on there. I clicked the button for sending messages and was informed that I need a premium subscription to do that.

I understand they want to earn money and making users pay for features is a way to do that. But this is not a new feature that they are offering. It’s something we had before. It’s called email. It’s very strange that they take that away from their users and charge for a (lesser) replacement. All they have to do is not show the email addresses in the profiles. Very lame.

It reminds me of an old Simpsons episode. Mr. Burns had darkened the sun above Springfield with a large shield so everyone had to pay for more electricity, which was provided by his power plant.

Getting Enough Sleep

In this post I don’t have any special idea in my mind to ramble about. This is just a “note to self”.

The message: Get more sleep.

I’ve been pushing myself hard lately. I’m not a big “you need routines” guy, but I do see their value. For instance getting a routine of writing these blog posts in place is great for exercising writing. For me anyway. But the problem is that I keep adding things onto my todo lists and my sleep schedule suffers.

A few days ago I actually slept so little that it lead to a lucid dream. You probably know what I mean. It’s a dream in which we know that we are dreaming. We are awake inside the dream. It was pretty wild. Interesting and trippy. But it came about because I slept to little and then fell asleep again and woke up soon after (and I guess, fell asleep again).

Long story short: My sleep schedule is messed up. This can’t be healthy.

On the other hand I don’t fall asleep watching Netflix or playing computer games. Lately I am pretty happy with what I do. I go to bed with a sense of accomplishment. (I won’t got into details on that however. Perhaps some other time.) This feels great.

But, alas, having to get up early does not.

I also think I drink way more coffee than the average person. (But I do not believe that too much coffee is bad for us. Unlike cigarettes or alcohol for example.)

And as you can probably tell, dear reader, I am quite tired now. But let me finish this post with something that just came to mind. Wow, a topic after all!

(Told you writing can take care of itself if we just start.)

The topic is pride.

Let me just ramble about pride for a second..

For a long time I didn’t get the concept of pride. What the big deal was. It seemed to be a bad emotion. Something like greed or envy. After all we are all the products of our genes and environment. What pride can we feel if we are, I don’t know, born smart or beautiful? Or if our parents or teachers taught us how how to behave properly so we are a success? Or if we got lucky playing some lottery? It’s not really our achievement. The universe kind of did that.

Well, to get it, I think we can choose to push ourselves really hard. I mean Arnold Schwarzenegger hard (“You start counting [reps] when it starts to hurt!”). Ok maybe not that hard..

But if we, for example, define some goals for ourselves and put a lot of tasks in our daily routine, and if we actually pull it off and do all what we promised ourselves we would do. Well, man (or girl), that feels pretty nice.

Yeah, I’m tired, but I feel good about myself right now. I actually did write something for the blog today.

I guess I’m a little proud of myself.

Shrug.