Giter Site home page Giter Site logo

freegeoip's Introduction

freegeoip

NOTE: as of April 2018 this repository is no longer active. Please visit https://github.com/apilayer/freegeoip/ for the current version.


Deploy

This is the source code of the freegeoip software. It contains both the web server that empowers freegeoip.net, and a package for the Go programming language that enables any web server to support IP geolocation with a simple and clean API.

See http://en.wikipedia.org/wiki/Geolocation for details about geolocation.

Developers looking for the Go API can skip to the Package freegeoip section below.

Running

This section is for people who desire to run the freegeoip web server on their own infrastructure. The easiest and most generic way of doing this is by using Docker. All examples below use Docker.

Docker

Install Docker

Docker has install instructions for many platforms, including

Run the API in a container

docker run --restart=always -p 8080:8080 -d fiorix/freegeoip

Test

curl localhost:8080/json/1.2.3.4
# => {"ip":"1.2.3.4","country_code":"US","country_name":"United States", # ...

Other Linux, OS X, FreeBSD, and Windows

There are pre-compiled binaries available.

Production configuration

For production workloads you may want to use different configuration for the freegeoip web server, for example:

  • Enabling the "internal server" for collecting metrics and profiling/tracing the freegeoip web server on demand
  • Monitoring the internal server using Prometheus, or exporting your metrics to New Relic
  • Serving the freegeoip API over HTTPS (TLS) using your own certificates, or provisioned automatically using LetsEncrypt.org
  • Configuring HSTS to restrict your browser clients to always use HTTPS
  • Configuring the read and write timeouts to avoid stale clients consuming server resources
  • Configuring the freegeoip web server to read the client IP (for logs, etc) from the X-Forwarded-For header when running behind a reverse proxy
  • Configuring CORS to restrict access to your API to specific domains
  • Configuring a specific endpoint path prefix other than the default "/" (thus /json, /xml, /csv) to serve the API alongside other APIs on the same host
  • Optimizing your round trips by enabling TCP Fast Open on your OS and the freegeoip web server
  • Setting up usage limits (quotas) for your clients (per client IP) based on requests per time interval; we support various backends such as in-memory map (for single instance), or redis or memcache for distributed deployments
  • Serve the default GeoLite2 City free database that is downloaded and updated automatically in background on a configurable schedule, or
  • Serve the commercial GeoIP2 City database from MaxMind, either as a local file that you provide and update periodically (so the server can reload it), or configured to be downloaded periodically using your API key

See the Server Options section below for more information on configuring the server.

For automation, check out the freegeoip chef cookbook or the (legacy) Ansible Playbook for Ubuntu 14.04 LTS.

To see all the available options, use the -help option:

docker run --rm -it fiorix/freegeoip -help

If you're using LetsEncrypt.org to provision your TLS certificates, you have to listen for HTTPS on port 443. Following is an example of the server listening on 3 different ports: metrics + pprof (8888), http (80), and https (443):

docker run -p 8888:8888 -p 80:8080 -p 443:8443 -d fiorix/freegeoip \
	-internal-server=:8888 \
	-http=:8080 \
	-https=:8443 \
	-hsts=max-age=31536000 \
	-letsencrypt \
	-letsencrypt-hosts=myfancydomain.io

You can configure the freegeiop web server via command line flags or environment variables. The names of environment variables are the same for command line flags, but prefixed with FREEGEOIP, all upperscase, separated by underscores. If you want to use environment variables instead:

$ cat prod.env
FREEGEOIP_INTERNAL_SERVER=:8888
FREEGEOIP_HTTP=:8080
FREEGEOIP_HTTPS=:8443
FREEGEOIP_HSTS=max-age=31536000
FREEGEOIP_LETSENCRYPT=true
FREEGEOIP_LETSENCRYPT_HOSTS=myfancydomain.io

$ docker run --env-file=prod.env -p 8888:8888 -p 80:8080 -p 443:8443 -d fiorix/freegeoip

By default, HTTP/2 is enabled over HTTPS. You can disable by passing the -http2=false flag.

Also, the Docker image of freegeoip does not provide the web page from freegeiop.net, it only provides the API. If you want to serve that page, you can pass the -public=/var/www parameter in the command line. You can also tell Docker to mount that directory as a volume on the host machine and have it serve your own page, using Docker's -v parameter.

If the freegeoip web server is running behind a reverse proxy or load balancer, you have to run it passing the -use-x-forwarded-for parameter and provide the X-Forwarded-For HTTP header in all requests. This is for the freegeoip web server be able to log the client IP, and to perform geolocation lookups when an IP is not provided to the API, e.g. /json/ (uses client IP) vs /json/1.2.3.4.

Database

The current implementation uses the free GeoLite2 City database from MaxMind.

In the past we had databases from other providers, and at some point even our own database comprised of data from different sources. This means it might change in the future.

If you have purchased the commercial database from MaxMind, you can point the freegeoip web server or (Go API, for dev) to the URL containing the file, or local file, and the server will use it.

In case of files on disk, you can replace the file with a newer version and the freegeoip web server will reload it automatically in background. If instead of a file you use a URL (the default), we periodically check the URL in background to see if there's a new database version available, then download the reload it automatically.

All responses from the freegeiop API contain the date that the database was downloaded in the X-Database-Date HTTP header.

API

The freegeoip API is served by endpoints that encode the response in different formats.

Example:

curl freegeoip.net/json/

Returns the geolocation information of your own IP address, the source IP address of the connection.

You can pass a different IP or hostname. For example, to lookup the geolocation of github.com the server resolves the name first, then uses the first IP address available, which might be IPv4 or IPv6:

curl freegeoip.net/json/github.com

Same semantics are available for the /xml/{ip} and /csv/{ip} endpoints.

JSON responses can be encoded as JSONP, by adding the callback parameter:

curl freegeoip.net/json/?callback=foobar

The callback parameter is ignored on all other endpoints.

Metrics and profiling

The freegeoip web server can provide metrics about its usage, and also supports runtime profiling and tracing.

Both are disabled by default, but can be enabled by passing the -internal-server parameter in the command line. Metrics are generated for Prometheus and can be queried at /metrics even with curl.

HTTP pprof is available at /debug/pprof and the examples from the pprof package documentation should work on the freegeiop web server.

The freegeoip package for the Go programming language provides two APIs:

  • A database API that requires zero maintenance of the IP database;
  • A geolocation http.Handler that can be used/served by any http server.

tl;dr if all you want is code then see the example_test.go file.

Otherwise check out the godoc reference.

GoDoc Build Status GoReportCard

Features

  • Zero maintenance

The DB object alone can download an IP database file from the internet and service lookups to your program right away. It will auto-update the file in background and always magically work.

  • DevOps friendly

If you do care about the database and have the commercial version of the MaxMind database, you can update the database file with your program running and the DB object will load it in background. You can focus on your stuff.

  • Extensible

Besides the database part, the package provides an http.Handler object that you can add to your HTTP server to service IP geolocation lookups with the same simplistic API of freegeoip.net. There's also an interface for crafting your own HTTP responses encoded in any format.

Install

Download the package:

go get -d github.com/fiorix/freegeoip/...

Install the web server:

go install github.com/fiorix/freegeoip/cmd/freegeoip

Test coverage is quite good, and test code may help you find the stuff you need.

freegeoip's People

Contributors

dam660 avatar emilburzo avatar fiorix avatar gleicon avatar gui avatar if-kenn avatar infertux avatar lpereira avatar lxfontes avatar mathieu-aubin avatar matthiasn avatar messerf avatar mourner avatar omercnet avatar own3mall avatar pierreozoux avatar samnissen avatar wbyoung avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

freegeoip's Issues

Error with importing?

Hi,

When I run "go run freegeoip.go", I have an error while importing:

    "github.com/bradfitz/gomemcache/memcache"
    "github.com/fiorix/go-web/http"
    "github.com/fiorix/go-web/mux"

Any tips? Thanks

Some country blocks missing

Hi Fiorix,

I would like to contribute some country blocks that are currently missing in your database, in case you want to include them. They are all from APNIC and correspond to the country "HK - Hong Kong S.A.R." You can confirm them at http://www.apnic.net/apnic-info/whois_search

203.92.217.0 - 203.92.217.103
223.16.0.0 - 223.19.255.255
118.140.0.0 - 118.143.255.255
203.186.96.0 - 203.186.127.255
219.76.0.0 - 219.79.255.255

Thanks for the nice service that you've created.

-Adrian

Performance Benchmark

For fun, I ran a blitz.io load test.

2 second timeout, start at 1 user, ramp up to 100 users. Running on my own DigitalOcean droplet with 2 CPUS and 2GB of memory.

Not very good results really. Very CPU bound.

screen shot 2014-03-07 at 9 04 17 pm

screen shot 2014-03-07 at 9 04 39 pm

CacheSize directive

Can you elaborate on CacheSize="51200". Is this is just a static file that is 512MB? What is a reasonable size? Any harm in setting to 2048MB?

Databse for German cities seems to be off

Hi,

I'm located in Munich, Germany. My ip_start should be 3647875626 as my IP Address is 217.110.42.42.

I generated the database and had a look through the tables. Using the lookup SQL with city_blocks.ip_start <= 3647875626 I get a latitude/longitude information somewhere "in the middle" of the country (no city_name, postal_code present). It should be fairly central Munich, tough.

Would be great to get this solved.

Set up a Host in Europe

It'd pretty super great if response times from Europe were a bit lower (I'm having a 95ms ping from a fiber entreprise-grade network in Paris).

Can my company sponsor a Digital Ocean server in Amsterdam?

Support for perfect forward secrecy

Can you add a few more directives to the <Listen> block to set the SSL cipher suite preference, as well as prefer server specified ciphers? This allows us to obtain perfect forward secrecy from https://www.ssllabs.com/ssltest.

<Listen addr=":443" log="true">
    <CertFile>...</CertFile>
    <KeyFile>...</KeyFile>
    <PreferServerCipherSuites>true</PreferServerCipherSuites>
    <CipherSuites>EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS</CipherSuites>
</Listen>

Not sending the correct http header content-type back for JSON

curl -i https://freegeoip.net/json/8.8.8.8
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Date: Sun, 09 Mar 2014 21:51:15 GMT
Content-Length: 185
Content-Type: text/plain; charset=utf-8

{"ip":"8.8.8.8","country_code":"US","country_name":"United States","region_code":"","region_name":"","city":"","zipcode":"","latitude":38,"longitude":-97,"metro_code":"","areacode":""

Should be:

Content-Type: application/json

SSL Support

Hey Alexandre, I love this service! Have you considered adding a HTTPS version of the endpoint? The SSL certificate is on me if you're interested :-)

BUG: X-Forwarded-For header might contain a list of comma separated IPs

I think this is a bug: if your server is behind more than one proxy the X-Forwarded-For header might contain a list of comma separated IPs which freegeoip still handles as one single IP giving a 400 Bad Request.

Apache documentation (http://httpd.apache.org/docs/2.2/mod/mod_proxy.html#x-headers ):

"Be careful when using these headers on the origin server, since they will contain more than one (comma-separated) value if the original request already contained one of these headers. For example, you can use %{X-Forwarded-For}i in the log format string of the origin server to log the original clients IP address, but you may get more than one address if the request passes through several proxies."

Thank you for looking into this and fixing it.

Redis Dependency

Hi, I'd just like to point out that you don't mention the dependency on Redis anywhere in the readme. Caused a minor headache for me.

Thanks for providing the code though!

Callbacks no longer work

I'm not sure if the GitHub version of this script is affected, but the version on freegeoip.net seems to have broken, as callbacks no longer work.

For example, if you access http://freegeoip.net/json/github.com?callback=doit It now returns:

{"ip":"207.97.227.239","country_code":"US","country_name":"United States","region_code":"TX","region_name":"Texas","city":"San Antonio","zipcode":"78218","latitude":29.4889,"longitude":-98.3987,"metro_code":"641","areacode":"210"}

Rather than what it used to return:

doit({"ip":"207.97.227.239","country_code":"US","country_name":"United States","region_code":"TX","region_name":"Texas","city":"San Antonio","zipcode":"78218","latitude":29.4889,"longitude":-98.3987,"metro_code":"641","areacode":"210"})

Anyone know why this might be?

Cheers

Pete

Sources for building the DB no longer available

Hi,
I just want to share my observation that the suggested sources for building the DB are no longer available.
http://ipinfodb.com/ip_database.php
http://ipinfodb.com/timezonedatabase.php

However the direct-links still works.
http://mirrors.ipinfodb.com/ipinfodb/ip_database/current/ipinfodb_one_table_full.csv.zip
http://mirrors.ipinfodb.com/ipinfodb/timezonedatabase/tz.csv.zip

As a possible replacement, http://software77.net/geo-ip/ looks quite good in terms of the way it's distributed and also license-wise. http://www.wipmania.com/en/base/ looks good but the license it's published under seems to be a deal-breaker.

Error 404:Page not found

There is an Error, when i query with the IP 217.71.97.50 it answers with a "404 page not found"

Region and City information is missing last few days

For the last 3-4 days the Region and City fields are blank. This occurs in web requests from my site, as well as just loading the home page. So far I've only tested with IP addresses from Canada and Ireland, but result is the same for both (Resource and City fields empty).

updatedb.py seems to be broken

When updated is run it returns this error

Downloading http://dev.maxmind.com/static/csv/codes/maxmind/region.csv
Downloading http://musta.sh/files/all_cities_in_the_world.csv.zip
Extracting all_cities_in_the_world.csv -> all_cities_in_the_world.csv
Checking http://geolite.maxmind.com/download/geoip/database/GeoLiteCity_CSV/GeoLiteCity-latest.zip
Downloading http://geolite.maxmind.com/download/geoip/database/GeoLiteCity_CSV/GeoLiteCity-latest.zip
Extracting GeoLiteCity_20130604/GeoLiteCity-Blocks.csv -> GeoLiteCity-Blocks.csv
Extracting GeoLiteCity_20130604/GeoLiteCity-Location.csv -> GeoLiteCity-Location.csv
Downloading http://geolite.maxmind.com/download/geoip/database/GeoIPCountryCSV.zip
Extracting GeoIPCountryWhois.csv -> GeoIPCountryWhois.csv
Importing GeoIPCountryWhois.csv: 79980 records!
Importing region.csv: Traceback (most recent call last):
File "updatedb.py", line 191, in
import_csv(curs, region_csv, "region_names")
File "updatedb.py", line 81, in import_csv
curs.executemany(q, rows)
sqlite3.OperationalError: table region_names has 3 columns but 1 values were supplied
rl:eclipse macbookpro$ sudo python updatedb.py
Importing GeoIPCountryWhois.csv: 79980 records!
Importing region.csv: Traceback (most recent call last):
File "updatedb.py", line 202, in
import_csv(curs, region_csv, "region_names")
File "updatedb.py", line 83, in import_csv
curs.executemany(q, rows)
sqlite3.OperationalError: table region_names has 3 columns but 1 values were supplied

Render main page for a specific IP

As per our email, it'd be nice to have the ability to render a map page for a specific IP address. I believe it could be done 100% in JS as opposed to having the server render a template. Perhaps a dirt map.html?q=ip would do it with minimum effort.

IPv6 Support

Is that on the radar at all? MaxMind claims to have some limited IPv6 database info.

Issues installing and setting up server.

Hi,
Thanks for the awesome freegeoip. I am attempting to run a server of my own so that I won't have to affect your servers.
I have never used go before so please bear with my lack of knowledge.
The process I used is:
install go: sudo apt-get install golang
install other reqs: sudo apt-get install build-essential libsqlite3-dev pkg-config
get your git code: sudo go get github.com/fiorix/freegeoip
attempting to build:
cd /usr/lib/go/src/pkg/github.com/fiorix/freegeoip
and then: go build

First I ran into:
/usr/lib/go/src/pkg/github.com/fiorix/go-redis/redis/redis.go:265: function ends without a return statement

After fixing the above by moving the return from the else outside the else statement, I get the following issue(while attempting go run):

/usr/lib/go/src/pkg/github.com/fiorix/freegeoip/freegeoip.go:273: enc.Indent undefined (type *xml.Encoder has no field or method Indent)

I hope you can help me fix the issue.
Thanks!

Unable to compile.

The below repositories dont exist anymore. Can you provide an alternate

go get github.com/fiorix/go-redis/redis
go get github.com/fiorix/go-web/httpxtra

sqlite3 import error on fresh install

Fresh install on fresh ubuntu server in VM.
$ go run freegeoip.go
panic: sql: unknown driver "sqlite3" (forgotten import?)

goroutine 1 [running]:
main.GeoipHandler(0x8215b00)
/home/jay/src/freegeoip-master/freegeoip.go:88 +0x86
main.main()
/home/jay/src/freegeoip-master/freegeoip.go:55 +0x188

goroutine 2 [runnable]:
exit status 2

I went back through the steps and I've run:
$ go get github.com/mattn/go-sqlite3
without any errors. I can see it's failing on line 88, where it's calling:
db, err := sql.Open("sqlite3", conf.IPDB.File)

I have confirmed that the db file was generated and it's configured right in the config file. I suspect a path or something may not be set right.

sqlite3 dependency error when build

Hi Guys,

When I try to build "freegeoip" with the command "go build" I get the follwoing error :

freegeoip.go:28:2: no buildable Go source files in /home/speakser/dev/tools/goapps/src/code.google.com/p/gosqlite/sqlite3

I am under an x64 Ubtuntu machine with Go v1.2

400 Bad Request when using locally

Hi fiorix,

I was working on this locally, and found that when I was running it locally I would always get this response:

2013/12/24 21:46:16 IP ::1 is not IPv4
2013/12/24 21:46:16 HTTP 400 GET "/json/google.com" (::1) :: 54.664us

I've created a fix for this in my own local copy, any interest in a pull request for this or is there an existing workaround?

Thanks for the service!

Doesn't work in my development environment

Since I'm developing a NodeJS application and spawn a server with hostname localhost:9000 I'm not able to use freegeoip api.

XMLHttpRequest cannot load http://freegeoip.net/json. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:9000' is therefore not allowed access. 

Is there a way to make this work?

Very slow, requests

We use freegeoip.net for all of our geo IP, and seeing very slow requests right now:

➜  ~  time curl https://freegeoip.net/json/71.202.155.214

curl: (56) SSLRead() return error -9846
curl https://freegeoip.net/json/71.202.155.214  0.05s user 0.01s system 0% cpu 17.170 total
➜  ~  time curl https://freegeoip.net/json/71.202.155.214
curl: (56) SSLRead() return error -9846
curl https://freegeoip.net/json/71.202.155.214  0.05s user 0.01s system 0% cpu 17.078 total

We are willing to pay you to fix this, and keep it fast and provide some sort of SLA. Is this possible?

Return IP country's official currency

This would be great for e-commerce settings where you want to present your customers with a default currency.

Any thoughts on this? Is this outside the scope of the project?

Thanks!

Lots of incorrect results

I've noticed many of the locations returned by freegeoip are incorrect. Asked a few people on twitter to confirm:

https://twitter.com/allspiritseve/status/314770027175890944

I downloaded the app and ran update_db, but searching my ip (24.11.55.89) still returned Lansing, MI instead of Ann Arbor, MI.

I'm not really sure how to figure out what's wrong, but happy to assist in debugging if there's anything you need me to do.

Returned xml sometime has 2 byte characters

http://freegeoip.net/xml/142.136.11.230

Returns

<Response>
<Ip>142.136.11.230</Ip>
<CountryCode>CA</CountryCode>
<CountryName>Canada</CountryName>
<RegionCode>QC</RegionCode>
**<RegionName>Québec</RegionName>**
<City>Dorval</City>
<ZipCode>h9p1j3</ZipCode>
<Latitude>45.45000076293945</Latitude>
<Longitude>-73.75</Longitude>
<MetroCode/>
<AreaCode/>
</Response>

The accent in Québec causes problems

SSL certificate does not validate peer list

Hey guys. Follow up from my previous request to support SSL: #22

Seems the certificate you purchased is not from a known provider.

~  curl https://freegeoip.net/geoip/8.8.8.8
curl: (60) Peer certificate cannot be authenticated with known CA certificates
More details here: http://curl.haxx.se/docs/sslcerts.html

curl performs SSL certificate verification by default, using a "bundle"
 of Certificate Authority (CA) public keys (CA certs). If the default
 bundle file isn't adequate, you can specify an alternate file
 using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
 the bundle, the certificate verification probably failed due to a
 problem with the certificate (it might be expired, or the name might
 not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
 the -k (or --insecure) option.

Not retrieving the city

Hi,

I only need the country of the ip address, not the city. Is there an option for the request to specify that, to avoid wasting resources on the server?

Support CORS

Are there any plans on supporting CORS requests?

JSONP works mostly but it doesn't expose the error event. Occasionally I have some IP's which result in a 404 error response. With JSONP I can't get the error response and therefore don't know why it failed. If i could catch the error then I would mark it as failed and then not look it up the next time.

Server keeps crashing

We installed an instance of freegeoip on a Amazon box. It works fast but the server crashes every now and then. Is there a tool that would monitor the server's status and relaunch it if it happens to crash? The Amazon AWS monitor says the servers load had been at 20% max.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.