tag:blogger.com,1999:blog-52691454739847711702024-03-05T18:28:49.592-08:00Bunwichbunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.comBlogger50125tag:blogger.com,1999:blog-5269145473984771170.post-55496879911934782562022-08-22T15:53:00.004-07:002022-08-22T15:55:27.398-07:00Setting up Express and Typescript August 2022<p>To learn express and typescript, I wanted to convert the default express skeleton app into a typescript one. This uses the tutorial link below and only adds minimal changes to the express framework.<br /></p><p><a href="https://expressjs.com/en/starter/installing.html">https://expressjs.com/en/starter/installing.html<br /></a></p><p>and some help from this url too</p><p><a href="https://blog.logrocket.com/how-to-set-up-node-typescript-express/">https://blog.logrocket.com/how-to-set-up-node-typescript-express/</a><br /></p><p><span style="font-size: small;"><span style="font-family: courier;"># sets up package.json<br />mkdir myexpress; cd myexpress<br />npm init -y <br /><br />###<br /># express<br />npm install express <br /><br /># creates an express project using pug templating instead of default jade<br />npx express-generator --view=pug <br /><br />npm install<br /><br /># to start http://localhost:3000/<br />DEBUG=myapp:* npm start<br /><br />###<br /># typescript<br /># save-dev packages used only during dev and does not need to be deployed to prod<br /># ts-node is cli/repl for typescript<br />npm install typescript ts-node --save-dev <br /><br /># https://devblogs.microsoft.com/typescript/writing-dts-files-for-types/<br />npm install @types/node @types/express --save-dev <br /><br />npx tsc --init # creates tsconfig.json<br /><br />###<br /># Problems<br /># 1. convert all the .js files into typescript<br /># 2. create new directory called dist or built to store the transpiled js<br /># 3. copy static files into dist<br /># 4. transpile ts into js<br /># 5. run the server using `node dist/index.js`<br /># 6. update package.json and tsconfig.json so that you can run `DEBUG=myapp:* npm start`<br /><br />## 1. convert all the .js files into typescript<br /><br /># adapt app.js into app.ts<br />npm install @types/http-errors @types/cookie-parser @types/morgan<br /><br /># routes/index.ts<br /><br />import express from "express";<br />const router = express.Router();<br /><br />router.get('/', function(req, res, next) {<br /> res.render('index', { title: 'Express' });<br />});<br /><br />export default router;<br /><br /># app.js<br />import createError from "http-errors";<br />import express from "express";<br />import path from "path";<br />import cookieParser from "cookie-parser";<br />import logger from "morgan";<br /><br />import indexRouter from "./routes/index";<br />import usersRouter from "./routes/users";<br />import {NextFunction, Request, Response} from "express-serve-static-core";<br /><br />const app = express();<br /><br />// view engine setup<br />app.set('views', path.join(__dirname, '../views'));<br /><br />//...</span></span></p><p><span style="font-size: small;"><span style="font-family: courier;"></span></span></p><p><span style="font-size: small;"><span style="font-family: courier;">app.use(express.static(path.join(__dirname, '../public')));</span></span></p><p><span style="font-size: small;"><span style="font-family: courier;">//...</span></span><span style="font-size: small;"><span style="font-family: courier;"> <br /></span></span></p><p><span style="font-size: small;"><span style="font-family: courier;">// error handler<br />app.use(function(err: any, req: Request, res: Response, next: NextFunction) {<br /> // set locals, only providing error in development<br /> res.locals.message = err.message;<br /> res.locals.error = req.app.get('env') === 'development' ? err : {};<br /><br /> // render the error page<br /> res.status(err.status || 500);<br /> res.render('error');<br />});<br /><br />app.listen(3000, '127.0.0.1');<br />export = app</span></span></p><p><span style="font-size: small;"><span style="font-family: courier;"></span></span></p><p><span style="font-size: small;"><span style="font-family: courier;">## 3. Update the views/public paths used in app.js<br /># </span></span><span style="font-size: small;"><span style="font-family: courier;"><span style="font-size: small;"><span style="font-family: courier;">views and public need to be updated to ../ as app.js will be in ./dist and these two dirs will be one level up. This has been done in the above code snippet.</span></span> <br /><br />## 4. transpile cli<br /># this will search all ts files from the root directory and store the js files into the dist directory with the same hierarchy<br />npx tsc --outDir dist<br /><br />## 5. run the server using `node dist/app.js`<br />With the addition of the last line above app.listen(//...), we can run node server using the `node` command.<br /><br />## 6. update package.json and tsconfig.json so that you can run `DEBUG=myapp:* npm start` <br /># tsconfig.json<br />"outDir": "./dist", /* Specify an output folder for all emitted files. */<br /><br /># package.json<br /># this exists<br /> "scripts": {<br /> "start": "node ./bin/www"<br /> },<br /><br /># edit ./bin/www<br />var app = require('../dist/app');</span></span></p><p><span style="font-size: small;"><span style="font-family: courier;"></span></span></p><p><span style="font-size: small;"><span style="font-family: courier;"># Remove the app.listen line in app.ts as it's not needed any more<br />app.listen(3000, '127.0.0.1');<br /><br /># and now it will work using the express way of starting the server<br />DEBUG=myapp:* npm start<br /><br />## Bonus<br /># You can add a build to "scripts" in package.json<br />"build": "npx tsc" <br /># or use the cli <br />`npx tsc --watch`</span></span><br /><br /></p>bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-88488646296957507512019-11-17T18:37:00.003-08:002019-11-17T18:37:45.988-08:00Fedora 30 Add another port for ssh'ing to get around some wifi filtersSome ISP's that offer free wifi will not allow you to ssh. To get around this you can set your ssh server to use another port like 8080.<br /><br />For Fedora 30<br /><br />1) sudo vim /etc/ssh/sshd_config<br /><br />Change<br /><br /><span style="font-size: x-small;"><span style="font-family: "Courier New", Courier, monospace;">#Port 22</span></span><br />to<br /><span style="font-size: x-small;"><span style="font-family: "Courier New", Courier, monospace;">Port 22<br />Port 8080</span></span><br /><br /># This allows two ports to connect to ssh<br /><br />2) Update selinux to allow ssh on port 8080<br />
<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New", Courier, monospace;">sudo semanage port -m -t ssh_port_t -p tcp 8080</span></span><br />
<br />
If you use -a you will get an error like <br /><span style="font-family: "Courier New", Courier, monospace;"><span style="font-size: x-small;">ValueError: Port tcp/8080 already defined</span></span><br /><br />If you -d you will get another error like<br /><span style="font-family: "Courier New", Courier, monospace;"><span style="font-size: x-small;">ValueError: Port tcp/8080 is defined in policy, cannot be deleted</span></span><br /><br />Use this to check:<br /><br /><span style="font-family: "Courier New", Courier, monospace;"><span style="font-size: x-small;">sudo semanage port -l | grep 8080<br />http_cache_port_t tcp 8080, 8118, 8123, 10001-10010<br />ssh_port_t tcp 8080, 22</span></span>bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-1235250761570459942019-08-17T15:43:00.001-07:002019-08-17T15:52:17.512-07:00Create an interface array consisting of a generic struct type in golangI was looking at how to get a result set from a golang sql query. It seemed that a lot of the examples explicitly defined the fields or declared a struct that are passed into the Scan() method such as:<br />
<br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">var id int</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">var name string</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">err = rows.Scan(&id, &name)</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">// or</span></span><br />
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">row = MyStruct{}</span></span><br />
<span style="font-size: small;"><br /></span>
<span style="font-size: small;"><span style="font-family: "courier new" , "courier" , monospace;">err = rows.Scan(&row.Id, &row.Name)</span></span><br />
<br />
This seemed like a lot of repetition if every query required this logic. My next thought was to see if I could pass in a struct, use reflect to obtain the fields and return a slice of values.<br />
<br />
Here are two examples, the first one uses uses append and requires type assertion to access the fields. The second example uses reflect.append and each field can be accessed directly from the element.<br />
<br />
Note: Additional checks should be added, such as making sure the address of the object is passed in.<br />
<br />
<b>First</b><br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Menlo, Monaco, 'Courier New', monospace; font-size: 12px; font-weight: normal; line-height: 18px;">
<div>
<span style="color: #569cd6;">package</span><span style="color: #d4d4d4;"> main</span></div>
<br />
<div>
<span style="color: #569cd6;">import</span><span style="color: #d4d4d4;"> (</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"fmt"</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"reflect"</span></div>
<div>
<span style="color: #d4d4d4;">)</span></div>
<br />
<div>
<span style="color: #569cd6;">type</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">MyStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">struct</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> Id </span><span style="color: #4ec9b0;">int</span></div>
<div>
<span style="color: #d4d4d4;"> Name </span><span style="color: #4ec9b0;">string</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">main</span><span style="color: #d4d4d4;">() {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">me</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> MyStruct{}</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">result</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">doIt</span><span style="color: #d4d4d4;">(</span><span style="color: #d4d4d4;">&</span><span style="color: #d4d4d4;">me)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">for</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">_</span><span style="color: #d4d4d4;">, </span><span style="color: #9cdcfe;">v</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">range</span><span style="color: #d4d4d4;"> result {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Printf</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"%d %s</span><span style="color: #d7ba7d;">\n</span><span style="color: #ce9178;">"</span><span style="color: #d4d4d4;">, v.(MyStruct).Id, v.(MyStruct).Name)</span></div>
<div>
<span style="color: #d4d4d4;"> }</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">doIt</span><span style="color: #d4d4d4;">(genericStruct </span><span style="color: #569cd6;">interface</span><span style="color: #d4d4d4;">{}) []</span><span style="color: #569cd6;">interface</span><span style="color: #d4d4d4;">{} {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">params</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> []</span><span style="color: #569cd6;">interface</span><span style="color: #d4d4d4;">{}{}</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">var</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> reflect.Value</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">structType</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> reflect.</span><span style="color: #dcdcaa;">TypeOf</span><span style="color: #d4d4d4;">(genericStruct).</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// First Element</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> reflect.</span><span style="color: #dcdcaa;">New</span><span style="color: #d4d4d4;">(structType).</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Id"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetInt</span><span style="color: #d4d4d4;">(</span><span style="color: #b5cea8;">1</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Name"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetString</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"one"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Printf</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"%#v</span><span style="color: #d7ba7d;">\n</span><span style="color: #ce9178;">"</span><span style="color: #d4d4d4;">, myStruct)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">params</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">append</span><span style="color: #d4d4d4;">(params, myStruct.</span><span style="color: #dcdcaa;">Interface</span><span style="color: #d4d4d4;">())</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// Second Element</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> reflect.</span><span style="color: #dcdcaa;">New</span><span style="color: #d4d4d4;">(structType).</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Id"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetInt</span><span style="color: #d4d4d4;">(</span><span style="color: #b5cea8;">2</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Name"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetString</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"two"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Printf</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"%#v</span><span style="color: #d7ba7d;">\n</span><span style="color: #ce9178;">"</span><span style="color: #d4d4d4;">, myStruct)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">params</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">append</span><span style="color: #d4d4d4;">(params, myStruct.</span><span style="color: #dcdcaa;">Interface</span><span style="color: #d4d4d4;">())</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">return</span><span style="color: #d4d4d4;"> params</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
</div>
<br />
<b>Second</b><br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Menlo, Monaco, 'Courier New', monospace; font-size: 12px; font-weight: normal; line-height: 18px;">
<div>
<span style="color: #569cd6;">package</span><span style="color: #d4d4d4;"> main</span></div>
<br />
<div>
<span style="color: #569cd6;">import</span><span style="color: #d4d4d4;"> (</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"fmt"</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"reflect"</span></div>
<div>
<span style="color: #d4d4d4;">)</span></div>
<br />
<div>
<span style="color: #569cd6;">type</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">MyStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">struct</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> Id </span><span style="color: #4ec9b0;">int</span></div>
<div>
<span style="color: #d4d4d4;"> Name </span><span style="color: #4ec9b0;">string</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">main</span><span style="color: #d4d4d4;">() {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> []MyStruct{}</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">doIt</span><span style="color: #d4d4d4;">(</span><span style="color: #d4d4d4;">&</span><span style="color: #d4d4d4;">myStruct)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">for</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">_</span><span style="color: #d4d4d4;">, </span><span style="color: #9cdcfe;">v</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">range</span><span style="color: #d4d4d4;"> myStruct {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Printf</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"%d %s</span><span style="color: #d7ba7d;">\n</span><span style="color: #ce9178;">"</span><span style="color: #d4d4d4;">, v.Id, v.Name)</span></div>
<div>
<span style="color: #d4d4d4;"> }</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">doIt</span><span style="color: #d4d4d4;">(genericStructArray </span><span style="color: #569cd6;">interface</span><span style="color: #d4d4d4;">{}) {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">var</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> reflect.Value</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">genericValue</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> reflect.</span><span style="color: #dcdcaa;">ValueOf</span><span style="color: #d4d4d4;">(genericStructArray).</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">genericType</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> genericValue.</span><span style="color: #dcdcaa;">Type</span><span style="color: #d4d4d4;">().</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// First Element</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> reflect.</span><span style="color: #dcdcaa;">New</span><span style="color: #d4d4d4;">(genericType).</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Id"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetInt</span><span style="color: #d4d4d4;">(</span><span style="color: #b5cea8;">1</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Name"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetString</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"one"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Printf</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"%#v</span><span style="color: #d7ba7d;">\n</span><span style="color: #ce9178;">"</span><span style="color: #d4d4d4;">, myStruct)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> genericValue.</span><span style="color: #dcdcaa;">Set</span><span style="color: #d4d4d4;">(reflect.</span><span style="color: #dcdcaa;">Append</span><span style="color: #d4d4d4;">(genericValue, myStruct))</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// Second Element</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">myStruct</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> reflect.</span><span style="color: #dcdcaa;">New</span><span style="color: #d4d4d4;">(genericType).</span><span style="color: #dcdcaa;">Elem</span><span style="color: #d4d4d4;">()</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Id"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetInt</span><span style="color: #d4d4d4;">(</span><span style="color: #b5cea8;">2</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> myStruct.</span><span style="color: #dcdcaa;">FieldByName</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Name"</span><span style="color: #d4d4d4;">).</span><span style="color: #dcdcaa;">SetString</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"two"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Printf</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"%#v</span><span style="color: #d7ba7d;">\n</span><span style="color: #ce9178;">"</span><span style="color: #d4d4d4;">, myStruct)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> genericValue.</span><span style="color: #dcdcaa;">Set</span><span style="color: #d4d4d4;">(reflect.</span><span style="color: #dcdcaa;">Append</span><span style="color: #d4d4d4;">(genericValue, myStruct))</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
</div>
<br />
<b>Output (same for both)</b><br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Menlo, Monaco, 'Courier New', monospace; font-size: 12px; font-weight: normal; line-height: 18px;">
<div>
<span style="color: #6a9955;">main.MyStruct{Id:5, Name:"one"}</span></div>
<div>
<span style="color: #6a9955;">main.MyStruct{Id:2, Name:"two"}</span></div>
<div>
<span style="color: #6a9955;">5 one</span></div>
<div>
<span style="color: #6a9955;">2 two</span></div>
</div>
bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-11743442547358919142019-06-08T16:10:00.002-07:002019-08-16T17:09:08.972-07:00Learning middleware patterns in Golang<span style="font-family: inherit;">Middlewares are often applied using a wrapping a method wrapping pattern <i>(chain of responsibility design pattern)</i>. To better understand how to do this in golang, I've started with the Handler interface and created a HandlerFunc that mimics the HandlerFunc in https://golang.org/src/net/http/server.go except I've replaced the args with (context string). This allowed me to trace the order that middlewares access the current context.</span><br />
<br />
<a href="https://golang.org/pkg/net/http/#Request.Context">func (r *Request) Context() context.Context</a><br />
<br />
Some useful links that helped guide me.<br />
<a href="https://www.calhoun.io/why-cant-i-pass-this-function-as-an-http-handler/">https://www.calhoun.io/why-cant-i-pass-this-function-as-an-http-handler/</a><br />
<a href="https://www.alexedwards.net/blog/making-and-using-middleware">https://www.alexedwards.net/blog/making-and-using-middleware</a><br />
<a href="https://github.com/justinas/alice">https://github.com/justinas/alice</a> Ended with an implementation that resembles this. Thx!<br />
<br />
Update July 2019: Middleware args changed to Handler instead of HandlerFunc <br />
<br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Menlo, Monaco, 'Courier New', monospace; font-size: 12px; font-weight: normal; line-height: 18px;">
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Menlo, Monaco, 'Courier New', monospace; font-size: 12px; font-weight: normal; line-height: 18px;">
<div>
<span style="color: #569cd6;">package</span><span style="color: #d4d4d4;"> main</span></div>
<br />
<div>
<span style="color: #569cd6;">import</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">"fmt"</span></div>
<br />
<div>
<span style="color: #6a9955;">// HandlerFunc, ServeHTTP match the go standard libs except</span></div>
<div>
<span style="color: #6a9955;">// (w ResponseWriter, r *Request) has been replaced by (context string).</span></div>
<div>
<span style="color: #6a9955;">// We treat this as a buffer that we can read from add values to.</span></div>
<div>
<span style="color: #6a9955;">// Analagous to reading GET/POST args from Request and adding</span></div>
<div>
<span style="color: #6a9955;">// Information to Request.context()</span></div>
<div>
<span style="color: #6a9955;">// https://golang.org/src/net/http/server.go</span></div>
<br />
<div>
<span style="color: #6a9955;">// This implements Handler interface because it matches signature, meaning it has a</span></div>
<div>
<span style="color: #6a9955;">// ServerHTTP method with the same argument types</span></div>
<br />
<div>
<span style="color: #569cd6;">type</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">Handler</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">interface</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(context </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">type</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">HandlerFunc</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">func</span><span style="color: #d4d4d4;">(context </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">)</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> (f HandlerFunc) </span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(context </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">) {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">f</span><span style="color: #d4d4d4;">(context)</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">baseHandler</span><span style="color: #d4d4d4;">(h Handler) Handler {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Before return baseHandler"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">return</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">HandlerFunc</span><span style="color: #d4d4d4;">(</span><span style="color: #569cd6;">func</span><span style="color: #d4d4d4;">(context </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">) {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Before baseHandler"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">context</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> context </span><span style="color: #d4d4d4;">+</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">" base"</span></div>
<div>
<span style="color: #d4d4d4;"> h.</span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(context) </span><span style="color: #6a9955;">// call ServeHTTP on the original handler</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"After baseHandler"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> })</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">first</span><span style="color: #d4d4d4;">(h Handler) Handler {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Before return first"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">return</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">HandlerFunc</span><span style="color: #d4d4d4;">(</span><span style="color: #569cd6;">func</span><span style="color: #d4d4d4;">(context </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">) {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Before first"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">context</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> context </span><span style="color: #d4d4d4;">+</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">" first"</span></div>
<div>
<span style="color: #d4d4d4;"> h.</span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(context) </span><span style="color: #6a9955;">// call ServeHTTP on the original handler</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"After first"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> })</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">second</span><span style="color: #d4d4d4;">(h Handler) Handler {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Before return second"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">return</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">HandlerFunc</span><span style="color: #d4d4d4;">(</span><span style="color: #569cd6;">func</span><span style="color: #d4d4d4;">(context </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">) {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Before second"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">context</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> context </span><span style="color: #d4d4d4;">+</span><span style="color: #d4d4d4;"> </span><span style="color: #ce9178;">" second"</span></div>
<div>
<span style="color: #d4d4d4;"> h.</span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(context) </span><span style="color: #6a9955;">// call ServeHTTP on the original handler</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"After second"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;"> })</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">IndexEndPoint</span><span style="color: #d4d4d4;">(s </span><span style="color: #4ec9b0;">string</span><span style="color: #d4d4d4;">) {</span></div>
<div>
<span style="color: #d4d4d4;"> fmt.</span><span style="color: #dcdcaa;">Println</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"Index EndPoint: "</span><span style="color: #d4d4d4;">, s)</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">type</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">Middleware</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">func</span><span style="color: #d4d4d4;">(Handler) Handler</span></div>
<br />
<div>
<span style="color: #569cd6;">type</span><span style="color: #d4d4d4;"> </span><span style="color: #4ec9b0;">MiddlewareStack</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">struct</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> middlewares []Middleware</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">NewMiddlewareStack</span><span style="color: #d4d4d4;">(middlewares </span><span style="color: #d4d4d4;">...</span><span style="color: #d4d4d4;">Middleware) MiddlewareStack {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">return</span><span style="color: #d4d4d4;"> MiddlewareStack{middlewares: middlewares}</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #6a9955;">// The middleware wrap pattern eg. second(first(baseHandler(IndexEndPoint))</span></div>
<div>
<span style="color: #6a9955;">// means you need to find the deepest method and work backwards -</span></div>
<div>
<span style="color: #6a9955;">// baseHandler, then first, then second.</span></div>
<div>
<span style="color: #6a9955;">// This implementation stores the middlewares in an array and can mutate the</span></div>
<div>
<span style="color: #6a9955;">// values beginning with the lowest to highest index; which has some</span></div>
<div>
<span style="color: #6a9955;">// readability benefits.</span></div>
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> (ms </span><span style="color: #d4d4d4;">*</span><span style="color: #d4d4d4;">MiddlewareStack) </span><span style="color: #dcdcaa;">EndPoint</span><span style="color: #d4d4d4;">(endPoint HandlerFunc) Handler {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">var</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">h</span><span style="color: #d4d4d4;"> Handler</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// first middlware in array can access the context first</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">for</span><span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">i</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">len</span><span style="color: #d4d4d4;">(ms.middlewares) </span><span style="color: #d4d4d4;">-</span><span style="color: #d4d4d4;"> </span><span style="color: #b5cea8;">1</span><span style="color: #d4d4d4;">; i </span><span style="color: #d4d4d4;">>=</span><span style="color: #d4d4d4;"> </span><span style="color: #b5cea8;">0</span><span style="color: #d4d4d4;">; i</span><span style="color: #d4d4d4;">--</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">mw</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> ms.middlewares[i]</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// for _, mw := range ms.middlewares {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">if</span><span style="color: #d4d4d4;"> h </span><span style="color: #d4d4d4;">==</span><span style="color: #d4d4d4;"> </span><span style="color: #569cd6;">nil</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">h</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">mw</span><span style="color: #d4d4d4;">(endPoint)</span></div>
<div>
<span style="color: #d4d4d4;"> } </span><span style="color: #c586c0;">else</span><span style="color: #d4d4d4;"> {</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">h</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">mw</span><span style="color: #d4d4d4;">(h)</span></div>
<div>
<span style="color: #d4d4d4;"> }</span></div>
<div>
<span style="color: #d4d4d4;"> }</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #c586c0;">return</span><span style="color: #d4d4d4;"> h</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
<br />
<div>
<span style="color: #569cd6;">func</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">main</span><span style="color: #d4d4d4;">() {</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// middleware function wrapping</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// Output: Index EndPoint: start second first base</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">f</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">second</span><span style="color: #d4d4d4;">(</span><span style="color: #dcdcaa;">first</span><span style="color: #d4d4d4;">(</span><span style="color: #dcdcaa;">baseHandler</span><span style="color: #d4d4d4;">(</span><span style="color: #dcdcaa;">HandlerFunc</span><span style="color: #d4d4d4;">(IndexEndPoint))))</span></div>
<div>
<span style="color: #d4d4d4;"> f.</span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"start"</span><span style="color: #d4d4d4;">)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">/*</span></div>
<div>
<span style="color: #6a9955;"> // array of middleware</span></div>
<div>
<span style="color: #6a9955;"> // Another version of above, but storing in an array</span></div>
<div>
<span style="color: #6a9955;"> middleWares := []MiddleWare{baseHandler, first, second}</span></div>
<br />
<div>
<span style="color: #6a9955;"> var hFunc HandlerFunc</span></div>
<div>
<span style="color: #6a9955;"> for _, mw := range middleWares {</span></div>
<div>
<span style="color: #6a9955;"> if hFunc == nil {</span></div>
<div>
<span style="color: #6a9955;"> hFunc = mw(IndexEndPoint)</span></div>
<div>
<span style="color: #6a9955;"> } else {</span></div>
<div>
<span style="color: #6a9955;"> hFunc = mw(hFunc)</span></div>
<div>
<span style="color: #6a9955;"> }</span></div>
<div>
<span style="color: #6a9955;"> }</span></div>
<br />
<div>
<span style="color: #6a9955;"> hFunc.ServeHTTP("start")</span></div>
<div>
<span style="color: #6a9955;"> */</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// middleware struct</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #6a9955;">// Index EndPoint: start base first second</span></div>
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">middlewareStack</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> </span><span style="color: #dcdcaa;">NewMiddlewareStack</span><span style="color: #d4d4d4;">(baseHandler, first, second)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> </span><span style="color: #9cdcfe;">hFunc</span><span style="color: #d4d4d4;"> </span><span style="color: #d4d4d4;">:=</span><span style="color: #d4d4d4;"> middlewareStack.</span><span style="color: #dcdcaa;">EndPoint</span><span style="color: #d4d4d4;">(IndexEndPoint)</span></div>
<br />
<div>
<span style="color: #d4d4d4;"> hFunc.</span><span style="color: #dcdcaa;">ServeHTTP</span><span style="color: #d4d4d4;">(</span><span style="color: #ce9178;">"start"</span><span style="color: #d4d4d4;">)</span></div>
<div>
<span style="color: #d4d4d4;">}</span></div>
</div>
</div>
bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-36360282490333798632017-11-16T23:59:00.001-08:002017-11-16T23:59:24.414-08:00Firefox 57 and lost some shortcuts on macThere was an old plugin called Customizeable Shortcuts that hadn't been updated for while and was not usable with Firefox 57. I was using it to remap the 'search location bar' shortcut.<br />
<br />
Since I already use karabiner to remap some modifier keys for macos, it might be able to use it instead of waiting for a new firefox shortcut addon.<br />
<br />
Note: If you're confused by the left_option/left_command it's cause I've first remap left_command to left_option. <br />
<br />
1) Have a look at some of the examples for karabiner shortcuts<br />
https://pqrs.org/osx/karabiner/complex_modifications/#key_specific<br />
<br />
2) Create a json and take note of the path<br />
<br />
<span style="font-family: "Courier New", Courier, monospace;">{<br /> "title": "Firefox command-d search location",<br /> "rules": [<br /> {<br /> "description": "command-d search location",<br /> "manipulators": [<br /> {<br /> "type": "basic",<br /> "from": {<br /> "key_code": "d",<br /> "modifiers": {<br /> "mandatory": ["left_option"],<br /> "optional": ["any"]<br /> }<br /> },<br /> "to": [<br /> {<br /> "key_code": "l",<br /> "modifiers": [<br /> "left_command"<br /> ]<br /> } <br /> ],<br /> "conditions": [<br /> {<br /> "type": "frontmost_application_if",<br /> "bundle_identifiers": [<br /> "^org\\.mozilla\\.firefox"<br /> ]<br /> }<br /> ]<br /> }<br /> ]<br /> }<br /> ]<br />}</span><br />
<br />
I saved this to my desktop with the name firefox-command-d.json<br />
<br />
What is going on? frontmost_application_if only runs the above shortcuts if it's the app focused.<br />
bundle_identifiers is your app id that you can find in the plist.<br />
<br />
3) Now run enter this in the url bar in firefox: karabiner://karabiner/assets/complex_modifications/import?url=file:///Users/<your name="" user="">/Desktop/firefox-command-d.json</your><br />
<br />
Enable this and you have your remap. bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-54797267483472586482017-01-06T10:30:00.001-08:002017-01-06T10:30:25.354-08:00Blurry Font in Firefox after updating to Linux Fedora 25 I recently did a clean update of fedora and found the font to render quite blurry.<br />
<br />
What I found out:<br />
<br />
1) gnome-tweak-tool font settings do not work. At the time of the post any of the font settings did not make a difference.<br />
<br />
2) You may start trying to use font-tweak-tool or font-manager. Be aware that these may create font config files in your ~/ or in ~/.config<br />
<br />
These may need to be deleted so that your gnome settings take precedence.<br />
<br />
<i>Note: I've installed microsoft and ubuntu fonts for linux.</i><br />
<br />
So what's the fix?<br />
<br />a) Go to Settings > Fonts and change the settings here to Anti Aliasing: rgba and Hinting: full<br />
<br />
At this point your terminal should look good.<br />
<br />
b) For me, firefox and sublime text had bad looking fonts.<br />
<br />There's a directory in /etc/fonts/conf.d that controls some additional font rendering. It's odd that there's no GUI to modify this directly.<br />
<br />
sudo ln -s /usr/share/fontconfig/conf.avail/10-hinting-full.conf /etc/fonts/conf.d/<br />
sudo rm /usr/share/fontconfig/conf.avail/10-hinting-slight.conf<br />
<br />
Log out and Log back in and things should be clearer.bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com1tag:blogger.com,1999:blog-5269145473984771170.post-69734506933016828712016-09-21T22:27:00.003-07:002016-09-23T00:33:09.638-07:00MacOS 10.12 sierra karibiner and seil are brokenAfter updating to macos sierra it seems seil and karabiner do not work any more. From the official site it looks like it will take a while before the replacement app karabiner-elements is ready for prime time.<br />
<br />
<a href="https://github.com/tekezo/Karabiner-Elements">https://github.com/tekezo/Karabiner-Elements</a><br />
<br />
1) Start Karibiner and take a screen shot of your current settings. Check off 'Show enabled only'<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBUe6lDKbhu49FkaG4pbBKSchPG8JnPdlcKjJe7cuOt2nE-yjRrc0aQShMnGlkzo00vHRxQIVBhX-qqRIHg1zGYdfZoNPma7N5vDgaDdDzjVaXhMsqkigdsbF5L9utjCseCU7PrNNqN_rJ/s1600/karabiner-settings.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBUe6lDKbhu49FkaG4pbBKSchPG8JnPdlcKjJe7cuOt2nE-yjRrc0aQShMnGlkzo00vHRxQIVBhX-qqRIHg1zGYdfZoNPma7N5vDgaDdDzjVaXhMsqkigdsbF5L9utjCseCU7PrNNqN_rJ/s1600/karabiner-settings.png" /></a><br />
<br />
2) Uninstall seil and karabiner.<br />
<br />
I found that macos would not shut down cleanly after this step. Like it was failing on closing a process and hanged. Seems to have went away after installing karabiner-elements.<br />
<br />
3) Install karabiner-elements and create the file ~/.karabiner.d/configuration/karabiner.json<br />
<br />
https://pqrs.org/latest/karabiner-elements-latest.dmg (mentioned in the above github README.md)<br />
<br />
4) To get back my settings I added the following remaps. <br />
<br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> {</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "profiles": [</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> {</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "name": "Default profile",</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "selected": true,</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "simple_modifications": {</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "caps_lock": "escape",</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "left_command": "left_option",</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "left_option": "fn",</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> "fn": "left_command"</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> }</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> }</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> ]</span></span><br />
<span style="font-size: x-small;"><span style="font-family: "courier new" , "courier" , monospace;"> } </span></span><br />
<br />
5) To get the names of keys to add to the above, you can't really use the karabiner event viewer app. I was seeing Command_L and Fn. The following file has a list of all the acceptable names. control-f for left_command and you can see other ones that might suit your needs.<br />
<br />
https://github.com/tekezo/Karabiner-Elements/blob/master/src/share/types.hpp<br />
<br />
Hope this helps.<br />
<br />bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com3tag:blogger.com,1999:blog-5269145473984771170.post-49999889333848986272016-03-12T09:37:00.002-08:002016-03-12T09:37:23.999-08:00Kernel Crashing after upgrading to Fedora 23After upgrading to from fedora 22 to fedora 23, I was unable to boot into linux due to a kernel crash. I was able to load up the previous kernel from 22 to get back to desktop.<br /><br />I thought it might be a bad grub config so I ran this to rebuild grub<br />grub2-mkconfig -o /boot/grub2/grub.cfg<br /><br />This produced a lot of errors such as: <br />ERROR: pdc: reading /dev/sdb[Input/output error]<br /><br />
It looks like the initramfs could be corrupt.<br />
<br />Solution:<br />sudo dracut --regenerate-all --force<br />sudo grub2-mkconfig -o /boot/grub2/grub.cfg<br />
<br />
No errors were produced at this time. bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-82586709688618090902015-10-12T00:29:00.001-07:002015-10-12T00:51:09.266-07:00Getting the fontNames from Swift with XCode 7.01<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">func fontForDisplay(atIndexPath indexPath: NSIndexPath) -> UIFont? {<br /> if indexPath.section == 0 {<br /> let familyName = familyNames[indexPath.row]<br /> let fontName = UIFont.fontNamesForFamilyName(familyName).first as String<br /> return UIFont(name: fontName, size: cellPointSize)<br /> } else {<br /> return nil<br /> }<br />}</span></span><br />
<br />
The above snippet of code is from <br />
Beginning iPhone Development with Swift Exploring the iOS SDK <br />
I'm trying this on el capitan and xcode 7.01, which now uses swift 2.0<br />
<br />
The first issue is that xcode will warn you that 'String?' is not convertible to 'String'<br />
Adding a ! to force cast and will allow the code to run. (append it to either first! or String!)<br />
<br />
The next issue is that this is thrown: EXC_BAD_EXCEPTION<br />
Looking at the trace, we can see<br />
<br />
familyName = (String) "Bangla Sangam MN"<br />
fontName = (String!) nil<br />
<br />
So it appears that we're trying to get the first element of an empty array. I ended up with this solution:<br />
<br /><span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;"> let fontArray: String? = UIFont.fontNamesForFamilyName(familyName).first<br /> let fontName = (fontArray != nil) ? fontArray! : ""</span></span><br />
<br />
Let me know if there is a more idiomatic way of doing this with Swift 2.0bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-63055071554865640332015-01-08T01:11:00.003-08:002015-01-08T01:12:20.605-08:00golang: Do you need a singleton? Where are my private/public class modifiers?Intro: Singletons can be useful, but as mentioned in other people's posts they are an anti pattern and can make testing and debugging difficult. A post on stack overflow had this short nonspecific message "Just put your variables and functions at the package level." <a href="http://stackoverflow.com/questions/1823286/singleton-in-go">http://stackoverflow.com/questions/1823286/singleton-in-go</a> I took this as a hint that with a little more knowledge of how go packages work, I could get a single instance of an object and have it abstracted so that modification would be difficult, if not impossible. <br />
<br />
Let's start with three files. <br />
<br />
src/logger/logger.go<br />
src/chat_server/main.go<br />
src/chat_server/sub/sub.go<br />
<br />
logger.go<br />
<br />
<pre style="background-color: white; color: black">package logger
import (
"fmt"
)
type logger struct {
Timestamp int
}
type Togger struct {
Timestamp int
}
var log = logger{Timestamp: 12345}
var Tog = Togger{Timestamp: 12345}
func (l *logger)writeInfoFile(s string) {
fmt.Println(s)
}
func (l *logger)writeErrorFile(s string) {
fmt.Println(s)
}
func Debug(s string) {
log.writeInfoFile(s)
fmt.Println(&log.Timestamp)
}
</pre>
<br />
There is a logger object named log with a single timestamp field. The other thing to note is that the functions, variables and structs (golang's version of a class) can have an upper or lower case first letter.<br />
<br />
"if something starts with a capital letter that means other packages (and programs) are able to see it" - http://www.golang-book.com/11/index.htm<br />
<br />
For those us who are used to having public and private keywords in our OO language, this capital letter convention is how go restricts access. This means that Togger, Tog, and Debug() can be referred to once logger is imported in another file. While log, loger and write*() can not. This takes a little closer to our goal because we should be able to instantiate an instance of logger, and only allow specific functions to act on it.<br />
<br />
main.go<br />
<br />
<pre style="background-color: white;color: black">package main
import (
"logger"
"chat_server/sub"
"fmt"
)
func main() {
logger.Debug("one")
logger.Debug("two")
sub.CheckingAddress()
isPublic := logger.Togger{Timestamp: 555}
fmt.Println(isPublic.Timestamp)
fmt.Println(logger.Tog.Timestamp)
// These will cause an error
// fmt.Println(logger.log.Timestamp)
// isPublic := logger.logger{Timestamp: 333}
}
</pre>
<br />
Here are some examples of how this works. Debug is a function that can be accessed after the import. It can refer to var log as it's within the same package. Trying to access logger.log directly is not allowed, while the analagous struct value logger.Tog can be called. Any attempt to init a new 'logger' object also fails.<br />
<br />
There is one more quick check that I wanted to verify and that is to confirm the log object continues to be the only instance no matter where it is imported.<br />
<br />
sub.go<br />
<br />
<pre style="background-color: white;color: black">package sub
import (
"logger"
)
func CheckingAddress() {
logger.Debug("In SUB")
}
</pre>
<br />
Way back in logger.go I print out the memory address of the Timestamp field.<br />
<br />
fmt.Println(&log.Timestamp)<br />
<br />
After running main, the output is:<br />
<br />
one<br />
0x547068<br />
two<br />
0x547068<br />
In SUB<br />
0x547068<br />
555<br />
12345<br />
<br />
We get the same address so it's good.<br />
<br />
Conclusion: I was able to create a single instance of my logger struct without resorting to a singleton and learned how go packages limit access to vars and and functions.bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-16372039418127638182014-12-17T20:17:00.000-08:002014-12-17T20:53:01.736-08:00VMware Player Free and changing boot devices.VMWare player free doesn't include all the settings that the commercial editions offer. In order to boot an iso, you must hand edit the *.vmx file and add the following settings. <br />
<br />
bios.bootOrder = "cdrom,hdd,floppy"<br />
bios.hddOrder = "scsi0:0,ide1:0" <br />
<br />
Adding the above information allowed me to install fedora 21 over my existing fedora 20.<br />
<br />
Tip: After installation, I powered the vm off. Removed the above lines and removed the fedora iso from the vmware cd drive. bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-46067882541896523922014-09-01T23:37:00.000-07:002014-09-01T23:37:18.497-07:00Using Chef to auto create an instance on Amazon ec2Chef is one of the major server automation tools out there along with Puppet and Ansible. I decided to give chef a try by auto creating an ec2 instance. They're all trying to get you to buy saas packages for nodes greater than around 5. I will be using the free account offered by opscode to store my recipes.<br />
<br />
<h3>
<span style="font-weight: normal;">1) Create a new chef-repo or use your current chef-repo</span></h3>
<br />
For testing I cloned a new chef-repo<br />
git clone git://github.com/opscode/chef-repo.git ec2chefrepo<br />
<br />
<h3>
2) From the previous tutorial ./chef-repo copy over ./chef-repo/.chef into our new chef-repo</h3>
<br />
<h3>
3) In Amazon Ec2 click on your name in the top right</h3>
<br />
I get a password old/new page. Instead go to the left side and click on Users.<br />
<br />
Then click on your email and then the security credential tab<br />
<br />
<h3>
4) Get the Access Keys and Secret Keys</h3>
<br />
Click on Manage Access Keys<br />
Create a new key and you will get two strings.<br />
Note: The secret key is show and available this one time. You will need to create new access keys if the secret key is lost.<br />
<br />
Access Key Id<br />
AKAJG6Z4AFQ5YPQ<br />
<br />
Secret Access Key<br />
Mw5sHvDgJRtAVP2vkA8gL8XJkvoZijhNMf <br />
<br />
<h3>
5) With the above access keys and your ec2 .pem add these lines to ec2chefrepo/.chef/knife.rb</h3>
<br />
<pre>knife[:aws_access_key_id] = 'AKAJG6Z4AFQ5YPQ'
knife[:aws_ssh_key_id] = 'bunwichchef'
knife[:aws_secret_access_key] = 'Mw5sHvDgJRtAVP2vkA8gL8XJkvoZijhNMf' </pre>
<br />
<br />
Note: the ssh_key_id is your key name without the pem<br />
<br />
<h3>
6) Create a gemfile to install some gems</h3>
<br />
gem install bundle<br />
rbenv rehash<br />
cd ~/ec2chefrepo/<br />
vim Gemfile<br />
<br />
<pre>source 'https://rubygems.org'
gem 'chef'
gem 'knife-ec2'</pre>
<br />
<br />
Note: I had to run this before running bundle installs<br />
sudo yum install gcc-c++<br />
<br />
bundle install<br />
<br />
<h3>
7) Create and Deploy An Instance</h3>
<br />
Had to run:<br />
gem install rb-readline unf<br />
http://aws.amazon.com/amazon-linux-ami/<br />
To get a list of AMI Image Ids<br />
<br />
<pre>knife ec2 server create \
--availability-zone us-east-1b \
--node-name bunwichchefinstance.demo \
--flavor t1.micro \
--image ami-ba18d2 \
--run-list "role[memcached]" \
--identity-file ~/.ssh/bunwichchef.pem \
--ssh-user ec2-user </pre>
<br />
<br />
<br />
<br />
<br />
<br />bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com1tag:blogger.com,1999:blog-5269145473984771170.post-88545926008447859892014-06-15T00:12:00.000-07:002014-08-03T23:38:32.258-07:00vlc no decoder module fedora 20Sometime after updating Fedora 19 to 20 (using fedup), VLC stopped playing some h264 videos.<br />
<br />
An error message such as this appeared:<br />
<br />
no suitable decoder module for fourcc `h264'. VLC probably does not support this sound or video format.<br />
<br />
<br />
<div style="-qt-block-indent: 0; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; text-indent: 0px;">
<span style="color: red;">No suitable decoder module:</span></div>
VLC does not support the audio or video format "h264". Unfortunately there is no way for you to fix this. <br /> <br /> It was missing lame-libs. A sudo yum install lame-libs solved my issue. <br /> <br /> What is more important is how I solved this: <br /> <br /> a) vlc -vvv mediafile.mp4 <br /> <br /> b) Look for yellow or red warning/error messages. A lot of information gets outputted. <br /> <br /> eg: <br /> 0x1666118] main libvlc warning: cannot load module `/usr/lib64/vlc/plugins/demux/libavformat_plugin.so' (libmp3lame.so.0: cannot open shared object file: No such file or directory)<br /> <br /> c) This message states that libmp3lame.so.0 does not exist. <br /> <br /> d) sudo repoquery --whatprovides '*/libmp3lame.so.0' <br /> <br /> returned: <br /> lame-libs-0:3.99.5-2.fc19.i686bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-19338667781423102322014-05-30T10:51:00.002-07:002014-05-30T10:58:18.786-07:00Failed to load libGL.so on Fedora 20 and Android emulatorI got this warning when trying to get the android emulator working on Fedora 20.<br />
<br />
You need to install 2 packages to get this working:<br />
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;"><br /></span></span>
<span style="font-size: x-small;"><span style="font-family: "Courier New",Courier,monospace;">sudo yum install mesa-libGL-devel mesa-libGL-devel.i686</span></span><br />
<br />
The libGL.so message disappeared after this. Command to search for this lib on future installs.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;"><span style="font-size: x-small;">sudo yum whatprovides */libGL.so</span></span>bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-44436708418581436662014-05-01T12:23:00.000-07:002014-05-01T12:23:42.035-07:00How humor and software development are related.I've been putting out a few resumes and getting back to an HR person with my status. Part of my response describes how having a funny bone has affected me as a developer.<br />
<br />
<blockquote class="tr_bq">
Hi XXX,
<br />
<br />Hope your talent search is going well for XXX. We had a short
but good talk last week and went over my qualifications and past work
experience. I enjoyed listening to what you and XXX were
looking for in prospective employees. I did my best to be as cool as
possible, but having our call dropped and me running around the all
corners of my building trying to find a good connection, might have
made me sound a little nervous <span class="moz-smiley-s1" title=":)"></span>
:)<br />
<br />My three main takeaways from our call was that culture, personality
and technology skills were equally valued by XXX.
<br />
<br />Coming from a small town, I feel that I was able to grow up in an
environment where being good to your neighbours and having great
friends were an important part of life. People still left their doors
unlocked and when you drive by in a car you wave your hand. I think I
certainly have brought this attitude with me as a Vancouverite, and
will wave to my neighbours when I bike or walk around my part of
town. I stopped doing this downtown as people looked at me strange
(except in downtown east side where they tried to hug me...ewww)
<br />
<br />Having not a lot to do in a small town also made you grow your
personality and one aspect is that I think I have a great sense of
humour and wit. All you have are your friends and when there wasn't
much to do we would sit around and make jokes. It was a game of one
upmanship, when someone said something funny, you tried your best to
build on it or say something even funnier. It's important to note
that humour can sometimes hurt people, and being careful not to cross
that line is part of the fun. I tend to respect Stephen Colbert's
type of humour, and know I'll never be as good. People have told me
that I'm funny, but I always tell them, "Really? I'm the least funny
person among my funny group of friends".
<br />
<br />This trait has helped me make friends and interact with people, but I
think it also has helped my career. Rule of comedy - funny comes in
threes. You tend to look at a situation or a phrase and think of
three things that you can add to it. It really helps with improving
your lateral thinking and I find that I apply this to all aspects of
my every day work. During a conversation or a question, I come up a
set of options, and try to mentally travel down each path and drop
the ones that don't work. Then express the good ones. Keep repeating
until the best solution is found. This is what developers do all day
I feel that it is one of my strongest attributes that one would
expect from someone who was more artsy.<br /><br />...</blockquote>
<br />
A large part of software development is analyzing a situation and choosing an option and testing the results. Comedy is analyzing a situation, finding the absurdity and testing among your peers. Nothing is funnier than seeing your TDD tests pasts, am I right? Is it no wonder that some great comedians had STEM backgrounds?<br />
<br />
Jimmy Fallon - CPSC (yes he dropped out for SNL)<br />
Mike Judge - Physics<br />
Rowan Atkinson - EEng<br />
Ray Romano - Accountingbunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com1tag:blogger.com,1999:blog-5269145473984771170.post-1157805593462706892014-02-12T00:59:00.001-08:002014-02-12T23:32:11.744-08:00Finally a MySQL connector that works with Django and Python 3The django community isn't the most supportive of mysql. They have valid arguments on why postgres is superior is to mysql and I don't disagree with them. Except that I have a level of comfort with MySQL that I've gotten from being paid to work with it the past six years. I'm not necessarily forgiving MySQL for its quirks, but I know I can depend on the large community and the vast resources if I ever run into problems. On the chance that one of my projects 'hockey sticks', there are experts who have gotten MySQL to scale with the traffic.<br />
<br />
For those that are techno puritans, they sometimes forget that MariaDB is a solid open initiative that deserves support from the community as it adheres to the same open source principles as Postgres. <br />
<br />
I've been patiently creating my app in Python 2.7 eagerly waiting for one of the MySQL connectors to work with Python 3 and Django. Finally in the past month MySQL released an official one. <br />
<br />
I tested this connector with the Django tutorial app and got ./manage.py syncdb to create some tables for my test models. More testing will be needed to see if south and other parts of the Django ORM are working correctly.<br />
<br />
<a href="http://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html">http://dev.mysql.com/doc/connector-python/en/connector-python-django-backend.html</a> <br />
<br />
System:<br />
Fedora 20<br />
Django<br />
Python 3.3 <br />
<br />
Step 1:<br />
sudo yum install python-virtualenv<br />
<br />
Step 2 - Create your python 3 environment:<br />
virtualenv -p /usr/bin/python3 myenv<br />
<br />
# On fedora python 3 is sym linked to python3.3<br />
<br />
cd myenv<br />
source bin/activate<br />
<br />
Step 3 - Install Django and the official mysql connector:<br />
pip install django # at the time of this writing it is 1.6.2.<br />
pip install mysql-connector-python<br />
<br />
# This matches the connector version from the mysql link above.<br />
# Downloading mysql-connector-python-1.1.5.zip (337kB): 337kB downloaded<br />
<br />
Step 4 - Configure Django settings.py to use this database connector:<br />
<span style="font-family: "Courier New",Courier,monospace;"><br /></span>
<span style="font-family: "Courier New",Courier,monospace;">DATABASES = {<br /> 'default': {<br /> 'NAME': 'mydatabase',<br /> 'ENGINE': 'mysql.connector.django',<br /> 'USER': 'myuser',<br /> 'PASSWORD': 'secretpassword',<br /> 'OPTIONS': {<br /> 'autocommit': True,<br /> },<br /> }<br />}</span><br />
<br />
Step 5:<br />
Create your models and run ./manage syncdb<br />
<br />
Update: Feb 12, 2014<br />
<a href="http://dev.mysql.com/doc/relnotes/connector-python/en/news-1-1-5.html">http://dev.mysql.com/doc/relnotes/connector-python/en/news-1-1-5.html</a><br />
<br />
Changes in MySQL Connector/Python 1.1.5 (2014-01-31)<br />
Functionality Added or Changed<br />
- Connector/Python is now compatible with Django 1.6. (Bug #17857712)<br />
<br />
You can find the Fedora 20 rpm from here as 1.1.5 is being tested:<br />
<a href="https://dl.fedoraproject.org/pub/fedora/linux/updates/testing/20/x86_64/mysql-connector-python3-1.1.5-1.fc20.noarch.rpm">https://dl.fedoraproject.org/pub/fedora/linux/updates/testing/20/x86_64/mysql-connector-python3-1.1.5-1.fc20.noarch.rpm </a><br />
<br />
I tested with Django 1.6.xbunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com11tag:blogger.com,1999:blog-5269145473984771170.post-87171949610783552452013-07-23T23:00:00.000-07:002013-07-23T22:22:27.197-07:00Can't watch mpeg-4 aac h.264 video in Linux FirefoxUpdated for Fedora 19 - July 2013<br />
<br />
Every new Fedora install, I forget how to watch apple trailers in my browser. I get the mpeg-4 aac and h.264 decoder missing message.<br />
<br />
This can be solved in three steps:<br />
<br />
1) Add the rpmfusion repository.<br />
<br />
<pre>su -c 'yum localinstall --nogpgcheck http://download1.rpmfusion.org/free/fedora/releases/19/Everything/x86_64/os/rpmfusion-free-release-19-1.noarch.rpm http://download1.rpmfusion.org/nonfree/fedora/releases/19/Everything/x86_64/os/rpmfusion-nonfree-release-19-1.noarch.rpm'</pre>
<br />
2) Install vlc<br />
<br />
sudo yum install vlc<br />
<br />
3) Lastly this one extra command allowed the movie to play<br />
<br />
sudo yum install gstreamer1-libavbunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-30744016707311934442013-07-10T00:24:00.000-07:002013-07-10T00:24:10.774-07:00Fedora 19 and Gnome 3.8 - Get back your terminal background transparencyGnome Terminal in 3.8 had the transparency option dropped/removed not because it wasn't a useful feature, but because implementation between new and old code was difficult.<br />
<br />
Anyways with Fedora 19 and Gnome 3.8, there is a way to get back this feature. I ended up using the window manager cinnamon as it has advanced features of gnome, yet includes lots of the intuitive right click menu options you expect on any desktop.<br />
<br />
Step 1:<br />
sudo yum install devilspie<br />
<br />
Step 2:<br />
mkdir ~/.devilspie<br />
<br />
Step 3:<br />
// Add any file in this dir ending in .ds and devilspie will process it.<br />
<br />vim ~/.devilspie/terminal-opacity.ds<br />
<br />
Step 4:<br />
// In this file add this line of code<br />
// Terminal is what fedora uses as the name of these terminals.<br />
<br />
(if<br />
(matches (window_name) "Terminal")<br />
(opacity 85)<br />
) <br />
<br />
Step 5:<br />
// Add in .bash_profile the following line. It will <br />
devilspie -a & <br />
<br />
Step 6: Logout and log back in.<br />
<br />
Any new terminal console windows will now be transparent - including the menu bars.bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com3tag:blogger.com,1999:blog-5269145473984771170.post-64857251552767187692013-06-02T03:03:00.001-07:002013-06-02T03:05:03.767-07:00Django change the trailing slash url convention to no trailing slashURL Specs and <a href="http://googlewebmastercentral.blogspot.com/2010/04/to-slash-or-not-to-slash.html" rel="nofollow">search engines</a> state that urls with and without trailing can affect your SEO rankings (and a user's ability to type in a link).<br />
<br />
eg. example.com/page and example.com/page/<br />
<br />
This affects some web frameworks, such as Django, as the regular expression for routing these URLs will be defined for only one of these cases. By convention Django will add a trailing slash, if a non trailing slash url is typed into the browser.<br />
<br />
I prefer to not have a trailing slash as it is one less character to type in. I should note that some sites, like stackoverflow.com or twitter.com does not give a crap either way.<br />
<br />
We can add this feature to Django by creating a custom middleware class that intercepts the request.path and rewrites it to the non trailing slash url.<br />
<br />
What is middleware?<br />
<br />
<i>Middleware is a framework of hooks into Django’s request/response processing.
It’s a light, low-level “plugin” system for globally altering Django’s input
or output.</i><br />
<br />
Or in layman's terms, it processes values/urls before it is sent to Django's views. You can find Django's middleware that redirects to the trailing slash url in:<br />
<br />
django/middleware/common.py<br />
<br />
Which was added to your project in<br />
settings.py<br />
<br />
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware',<br />
<br />
<br />
How to get Django to redirect trailing slashes to the non trailing slash url if it exists.<br />
<br />
Step 1:<br />
<br />
Add this line in settings.py<br />
<br />
APPEND_SLASH = False<br />
<br />
Step 2:<br />
<br />
Create these paths and files<br />
<br />
./common/<br />
./common/__init__.py<br />
./common/redirect.py<br />
<br />
Step 3: Add the class to the MIDDLEWARE definition<br />
<br />
MIDDLEWARE_CLASSES = (<br />
'common.redirect.RedirectTrailingSlashMiddleware',<br />
'django.middleware.common.CommonMiddleware',<br />
<br />
# It must be the first class as we want to catch it before django does.<br />
<br />
Step 4: Add this code to redirect.py<br />
<br />
For /admin urls, I have kept the trailing slash as I don't want to break Django's admin methods <br />
<br />
<pre>from django.conf import settings
from django.core import urlresolvers
from django import http
'''
Based on django/middleware/common.py
Django convention is to add trailing slashes to most urls
This method does the opposite and redirects trailing slashes to the
no trailing slash url if it exists
'''
class RedirectTrailingSlashMiddleware(object):
def process_request(self, request):
if settings.APPEND_SLASH:
return
if '/admin' in request.path:
settings.APPEND_SLASH = True
return
new_url = old_url = request.path
if (old_url.endswith('/')):
urlconf = getattr(request, 'urlconf', None)
if (not urlresolvers.is_valid_path(request.path_info, urlconf) and
urlresolvers.is_valid_path(request.path_info[:-1], urlconf)):
new_url = new_url[:-1]
if settings.DEBUG and request.method == 'POST':
raise RuntimeError((""
"You called this URL via POST, but the URL ends "
"in a slash and you have APPEND_SLASH set. Django can't "
"redirect to the non-slash URL while maintaining POST data. "
"Change your form to point to %s (note no trailing "
"slash), or set APPEND_SLASH=True in your Django "
"settings.") % (new_url))
if new_url == old_url:
# No redirects required.
return
return http.HttpResponsePermanentRedirect(new_url)
</pre>
bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com1tag:blogger.com,1999:blog-5269145473984771170.post-88340447536604784352013-04-17T13:34:00.000-07:002013-06-04T11:35:01.877-07:00Basic Master Slave setup on MySQL 5.5There are more than enough master slave mysql tutorials, and I'm adding another one to the pile for my own personal reference. <br />
<br />
<b>Setup:</b><br />
Two micro ec2 instances on amazon with mysql55 installed. Make sure port 3306 is open between servers.<br />
<br />
<b>Step 1: Edit /etc/my.cnf on master and slave</b><br />
<br />
On master: <br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">[mysqld]<br />log-bin=mysql-bin<br />server-id=1</span><br />
<br />
On slave<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">[mysqld]<br />server-id=2</span><br />
<br />
Side Note: you can't put master-host settings here as they've been deprecated since 5.1.17. MySQL will save the values internally and will automatically reference them when a reboot is done.<br />
<br />
Restart Both Servers<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">service mysqld restart</span><br />
<br />
<b>Step 2: Create Slave User On Master</b><br />
<br />
On Master run the mysql command:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">CREATE USER 'slave2'@'[SLAVE IP OR ADDRESS]' IDENTIFIED BY '[Fancy Password]';</span><br />
<span style="font-family: "Courier New",Courier,monospace;">GRANT REPLICATION SLAVE ON *.* TO 'slave2'@'[SLAVE IP OR ADDRESS]';</span><br />
<br />
Side Note: mydbname.* will not work, must use *.*<br />
<br />
<b>Step 3: Finish current commands and lock the tables</b><br />
<br />
On Master:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">flush tables with read lock</span><br />
<br />
This will finish all commands and stop new ones from happening. To release the locks we need to run unlock tables, but not till later.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">show master status<br /><br />+------------------+----------+--------------+------------------+<br />| File | Position | Binlog_Do_DB | Binlog_Ignore_DB |<br />+------------------+----------+--------------+------------------+<br />| mysql-bin.000002 | 1859 | | |<br />+------------------+----------+--------------+------------------+</span><br />
<br />
We'll have to keep track of the file and position if we use<br />
--lock-all-tables instead of --master-data. I'm using the latter<br />
<br />
Don't close your mysql console as this will unlock the tables. For the next step create a new terminal on the master server.<br />
<br />
<b>Step 4: Create a dump of the data on the master server</b><br />
<br />
On master run:<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">mysqldump -u root -p --all-databases --master-data > moodle.sql</span><br />
<br />
and copy the file to the slave server. <br />
<br />
<b>Step 5: Setup the slave server with the master login info.</b><br />
<br />
On slave go to mysql command prompt<br />
<span style="font-family: "Courier New",Courier,monospace;"><br />stop slave;<br /><br />CHANGE MASTER TO<br />MASTER_HOST='</span><span style="font-family: "Courier New",Courier,monospace;">[MASTER IP OR ADDRESS]',<br />MASTER_USER='slave2',<br />MASTER_PASSWORD='</span><span style="font-family: "Courier New",Courier,monospace;">[Fancy Password]';</span><br />
<br />
# MASTER_LOG_FILE='mysql-bin.000002',<br />
# MASTER_LOG_POS=1859;<br />
<br />
On the mysql doc site, these two lines are not needed as they are included in the dump file when use used --master-data<br />
<br />
<b>Step 6: Import the dump sql file on the slave server.</b><br />
<br />
Use this to import the dump file. (As mentioned this will add the master log file pos too.)<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">mysql -u root -p < moodle.sql</span><br />
<br />
<b>Step 7: Start the replication</b><br />
<br />
We still have that mysql command prompt on master so we are now ready to release the lock.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">unlock tables;</span><br />
<br />
Then on slave we can begin the replication<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">start slave;</span><br />
<br />
<b>Step 8: Confirm the slave is working</b><br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">show slave status\G</span><br />
<br />
and you should see<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">...</span><br />
<span style="font-family: "Courier New",Courier,monospace;">Slave_IO_Running: Yes<br />Slave_SQL_Running: Yes</span><br />
<span style="font-family: "Courier New",Courier,monospace;">...</span><br />
<br />
---<br />
<br />bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-70780466332524896662012-11-02T12:10:00.002-07:002012-11-02T12:10:37.080-07:00Moodle Query to Retrieve Outcomes Completed in Recent WeeksTo track outcome progress in Moodle for the past week, this ad-hoc aka custom query reports, lists the numbers of outcomes completed each week. It is formatted to show the weekly total for each course as shown in this image:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDw6ncQdCzMo8voTcDBZ4FtUFGY1bRzv-tyL_pts269Bk3SWkMixqLPASBezJuVYZYg2fhiuqD04-qTQKfwbZcmdUgjJcrZAANa9D1WFj4aeNbCpC1Wf8mAP9Wiv96aNI48Ay9edI6UF20/s1600/outcomes-per-week.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="260" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiDw6ncQdCzMo8voTcDBZ4FtUFGY1bRzv-tyL_pts269Bk3SWkMixqLPASBezJuVYZYg2fhiuqD04-qTQKfwbZcmdUgjJcrZAANa9D1WFj4aeNbCpC1Wf8mAP9Wiv96aNI48Ay9edI6UF20/s400/outcomes-per-week.png" width="400" /></a></div>
<br />
<br />
<br />
<pre>-- GROUP_CONCAT lists all the weeks and the standards completed in that week in a single table cell
-- By adding a order by in the group concat, we get the proper ordering of weeks (weeks were in the incorrect order without it)
-- CHAR(63) because the '?' is not accepted by Moodle Ad-Hoc Queries.
SELECT
outcomes.courseid,
CONCAT('<a href="http://www.blogger.com/%%WWWROOT%%/grade/report/outcomes/index.php%27,%20CHAR(63),%20%27id=%27,%20outcomes.courseid,%20%27">', C.fullname,'</a>'
) as course_name,
CONCAT(
GROUP_CONCAT(
CONCAT(outcomes.weekstr, concat(' [', outcomes.count, ']'))
ORDER BY courseid ASC, w ASC
SEPARATOR '
'
), '
Total:', SUM(outcomes.count)
) as outcomes_per_week
FROM
(
-- This sub query combines the three queries used by Moodle to get the outcome count
-- The WHERE statement
-- a) gets the day 16 weeks ago
-- b) We want to include results beginning on Sunday of that week
-- The SELECT weekstr - each day belongs to a week. We match each day with the start of its week.
-- eg. For the week of Wed Jan 5, the weekstr would be Sun-2
SELECT
goc.courseid, COUNT(gg.finalgrade) AS count,
DATE_FORMAT(
str_to_date(
concat(year(from_unixtime(gg.timemodified)), LPAD(week(from_unixtime(gg.timemodified)), 2, 0), 'sunday' ),
'%X%V %W'),
'%b-%e') weekstr,
week(from_unixtime(gg.timemodified)) as w
FROM prefix_grade_outcomes go
JOIN prefix_grade_outcomes_courses goc
ON go.id = goc.outcomeid
JOIN prefix_grade_items as gi
ON goc.outcomeid = gi.outcomeid AND
gi.courseid = goc.courseid
JOIN prefix_grade_grades as gg
ON gg.itemid = gi.id
WHERE gg.timemodified >= UNIX_TIMESTAMP(STR_TO_DATE(DATE_FORMAT(DATE_SUB(NOW(), INTERVAL 16 week), '%Y%V Sunday'), '%X%V %W'))
GROUP BY courseid, week(from_unixtime(gg.timemodified))
) as outcomes
JOIN prefix_course as C
ON C.id = outcomes.courseid
GROUP BY courseid
ORDER BY C.fullname asc
</pre>
<br />
Note: Optimization can be done to move the weekstr to the outside query. bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-45327253577669809512012-08-02T00:17:00.002-07:002012-08-26T21:17:31.498-07:00Run only a single instance of a cron job and prevent overlapWhen dealing with web applications often a cron process must be executed at most once. If a cron job overlaps, database queries can cause performance issues or at worse deadlocks and stale processes.<br />
<br />
Here is a script that solves this problem. Explained with detail as there are a lot of things happening in 5 lines of code. <br />
<br />
<pre>#!/bin/bash
# Installation
# mkdir /var/run/moodle
# chown root.apache /var/run/moodle
# chmod 775 /var/run/moodle
# copy this file and make it executable by the cron user. </pre>
<pre># chmod this file 744</pre>
<pre># add it to crontab or crontab -e -u apache </pre>
<pre> </pre>
<pre># Explanation
# 1. set -e tells a bash script to exit whenever a non zero value is i
# returned (0 means function executed without error)
# 2. flock needs 200 or any int to label the file descriptor
# 3. The ( brackets ) execs each line of commands in order and check to
# see if they return 0.
# 4. 200> tells the fd 200 to create the lock file if it doesn't already
# exist
# 5. -n nonblock, will return 1 if the lock is taken. as cron is being
# ran every 5-10 mins we can wait for the next one
# 6. trap, if cntrl-c is called or a command is killed, it will execute </pre>
<pre># the command and exit. Our case it removes the lock file.
# Note: This works great for cron and flock files. May be an issue with </pre>
<pre># race conditions if something other than flock eg. echo 'busy' > file.pid.
LOCKFILE=/var/run/moodle/moodlecron.lock
set -e
(
flock -n 200
trap "rm $LOCKFILE" EXIT
# Add commands to execute
/usr/bin/php /var/www/html/moodle/admin/cli/cron.php
) 200>$LOCKFILE</pre>
bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-22914195876458045822012-06-09T22:57:00.001-07:002012-06-09T22:57:21.838-07:00Get your page to highlight in Moodle's navigation MenuMoodle 2.3+ is able to automatically determine the menu items to highlight in the navigation menu. While working on one of my current projects, I was unable to make the current page highlight and I went looking for the Moodle method that do this.<br />
<br />
I have a custom reports module that is located in report/mycustomreports<br />
<br />
To add a custom report specific to a course and under the report menu item you add this bit of code to lib.php file.<br />
<br />
<pre>// File report/mycustomreport/lib.php
function report_mycustomreports_extend_navigation_course($navigation, $course, $context) {
global $CFG, $OUTPUT;
if (has_capability('report/mycustomreports:viewcoursereports', $context)) {
$url = new moodle_url('/report/mycustomreports/course/index.php', array('id'=>$course->id));
$navigation->add(get_string('mycustomreports', 'report_mycustomreports'), $url, navigation_node::TYPE_SETTING, null, null, n
ew pix_icon('i/report', ''));
}
}
</pre>
<br />
Take note of the URL and how it will end up looking:<br />
example.com/report/mycustomreports/course/index.php?id=55<br />
<br />
Now to make sure that the link to this report in the courses menu receives a highlight and expands the window, you must add a $PAGE->set_url() in the index.php<br />
<br />
<pre>// File: report/mycustomreports/course/index.php
$PAGE->set_url('/report/mycustomreports/course/index.php', array('id' => $course->id));
</pre>
<br />
Both URL's now match.<br />
<br />
If we click on the [Course Name] -> Reports -> My Custom Reports the page will load AND most importantly the link in the navigation menu will be highlighted.bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-87168641304363011572012-03-29T16:00:00.004-07:002012-03-29T16:04:19.886-07:00Passwordless login with multiple id_rsa and ssh identitiesPrimarily for my benefit as this topic can be found on tons of google searches. I have different user names such as ~bunwich and ~sandwich on a variety of servers. I want to be able to login without a password by entering <b>ssh bunwich@example1.com</b> or <b>ssh sandwich@example2.com</b><br />
<br />
On my computer, I have two different id_rsa, one for each account. (Also the corresponding id_rsa.pub) The goal is to automatically choose the correct id_rsa for each username and login without a password.<br />
<br />
1) ssh allows you to manage multiple identies using a wild cards and filtering by remote hostname and remote username. You can also filter by local hostname and local username.<br />
<br />
From the manual<br />
<i>"The file name may use the tilde syntax to refer to a user's home
directory or one of the following escape characters: '%d' (local user's
home directory),
'%u' (local user name), '%l' (local host name), '%h' (remote host name)
or '%r' (remote user name)."</i><br />
<br />
2) Create the following dirs<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
~/.ssh/ids/bunwich</div>
<div style="font-family: "Courier New",Courier,monospace;">
~/.ssh/ids/sandwich</div>
<br />
3) Copy the id_rsa belonging to each user into these dirs<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
~/.ssh/ids/bunwich/id_rsa </div>
<div style="font-family: "Courier New",Courier,monospace;">
~/.ssh/ids/sandwich/id_rsa</div>
<br />
chmod id_rsa to 600 if it isn't already <br />
<br />
4) Add an IdentityFile entry to you ssh config file<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
vim ~/.ssh/config</div>
<br />
Add the following line:<br />
<div style="font-family: "Courier New",Courier,monospace;">
<br /></div>
<div style="font-family: "Courier New",Courier,monospace;">
IdentityFile ~/.ssh/ids/%r/id_rsa<br />
</div>
<div style="font-family: inherit;">
An alternative is to also include a host name for each username.</div>
<div style="font-family: inherit;">
<br /></div>
<div style="font-family: inherit;">
eg.</div>
<pre style="font-family: inherit;"><span style="font-family: "Courier New",Courier,monospace;">IdentityFile ~/.ssh/ids/</span><b style="font-family: "Courier New",Courier,monospace;">%h</b><span style="font-family: "Courier New",Courier,monospace;">/</span><b style="font-family: "Courier New",Courier,monospace;">%r</b><span style="font-family: "Courier New",Courier,monospace;">/id_rsa</span> </pre>
<pre style="font-family: inherit;"> </pre>
5) Now make sure that both servers example1 and example2 have a ~/.ssh/authorized_keys and you'll be able to do passwordless logins.<br />
<br />
(You create authorized_keys by renaming the id_rsa.pub or appending the id_rsa.pub to the current authorized_keys)<br />
<br />
<br />
<br />
Extra - While you're messing with your config file, why not add an extra visual measure to make sure your host hasn't changed.<br />
<br />
<span style="font-family: "Courier New",Courier,monospace;">VisualHostKey yes to ~/.ssh/config</span><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com0tag:blogger.com,1999:blog-5269145473984771170.post-52949973812134163592011-12-30T05:44:00.000-08:002011-12-30T14:31:01.504-08:00Solution to Atheros AR9285 Wireless Card - Pinging works, but browsing the web does not.A few years back I purchased a Compaq CQ62-215DX notebook for $300.00. Based on the AMD V120 CPU, it is all the power you need to watch movies, run microsoft word an surf the web.<br />
<br />
Recently I updated some drivers, or I think I did during a routine Windows Update, and afterwards I was unable to surf the web. I was able to ping google.com/yahoo.com, but could not retrieve pages for major web sites. Other laptops worked so I knew it wasn't a router issue.<br />
<br />
Doing a search yielded plenty of results with people having the same problem.<br />
<br />
<div style="font-family: inherit;">
<b>System:</b> </div>
<div style="font-family: inherit;">
Windows 7 64-bit Home Edition</div>
<div style="font-family: inherit;">
Netgear WNDR3700 - has b/g/n and supports 2.5 and 5ghz. 150mbps to 300 mbps.</div>
<span style="font-family: inherit;">Compaq CQ62-215DX Atheros AR9285 b/g/n</span><br />
<br />
<span style="font-size: large;"><b>Step 1: Try all the drivers available for this card</b></span> <br />
<br />
There are about 2-3 driver packages on hp.com and the sketchy www.atheros.cz site. <br />
<br />
<a href="http://h10025.www1.hp.com/ewfrf/wc/softwareDownloadIndex?cc=us&lc=en&dlc=en&softwareitem=ob-91782-1">Link to the Atheros 2011 drivers</a> sp52131.exe<br />
<a href="http://www.atheros.cz/atheros-wireless-download.php?chipset=37&system=6">Link to atheros.cz drivers</a><br />
<br />
I probably installed these 20 times and still got no connectivity. Not to mention the Auto Update Installation on Windows 7 home would keep trying to install the old drivers without my permission. (gpedit.msc is not available on windows 7 home which lets you stop this from happening).<br />
<br />
<span style="font-size: large;"><b>Step 2: Found a post with a possible solution</b> </span><br />
<br />
After spending a few days researching, I stumbled upon a post on the hp forums where a user who had an ASUS laptop turned off the Wireless Mode from Auto to b/g and then was able to connect.<br />
<br />
Problem is when you go to device properties for your wireless network card you may not have a Wireless Mode setting. I reinstalled all the old drivers to see if there was a wireless mode setting in previous versions and nope, HP did not make these settings available.<br />
<br />
<b><span style="font-size: large;">Step 3: Look at the .inf files</span></b><br />
<br />
The next step was to determine where in the registry the advanced settings for the atheros wireless card were located. Long story short I was able to track the location of the registry keys used to configure the device, and I found a bunch of registry settings in the .inf files from the atheros.cz drivers. Next would be to add the registry settings to my Windows 7 registry.<br />
<br />
<b><span style="font-size: large;">Solution</span></b><br />
<br />
<b><i>TLDR; Wireless N did not work on the AR9285. Might be hardware, might be drivers. Whatever is I had to turn it off so that I could at least connect to the internet.</i></b><br />
<br />
I first tried to unpack the driver packages and modify the .inf files so I could get the setup.exe to do this for me. After a few failed attempts I gave up trying to automate key registration, and instead went with hand editing the registry. (yes regedit.exe can blue screen/kill your computer so be careful)<br />
<br />
From the .inf file in the atheros.cz we have these settings.<br />
<br />
<div style="font-family: "Courier New",Courier,monospace;">
<span style="font-size: x-small;">
HKR, Ndi\params\NetBand, ParamDesc, 0, %WirelessMode%<br />
HKR, Ndi\params\NetBand,</span><span style="font-size: x-small;"> </span><span style="font-size: x-small;">Base, 0, "10"<br />
HKR, Ndi\params\NetBand,</span><span style="font-size: x-small;"> </span><span style="font-size: x-small;">default, 0, "26636"<br />
HKR, Ndi\params\NetBand,</span><span style="font-size: x-small;"> </span><span style="font-size: x-small;">type, 0, "enum"<br />
HKR, Ndi\params\NetBand\enum,</span><span style="font-size: x-small;"> </span><span style="font-size: x-small;">"26636", 0, %WirelessModeAuto%<br />
HKR, Ndi\params\NetBand\enum,</span><span style="font-size: x-small;"> </span><span style="font-size: x-small;">"12",
0, %WirelessMode11bgOnly%<br />
<br />
[Strings]<br />
WirelessMode = "Wireless Mode Selection"<br />
WirelessMode11bgOnly = "802.11b/g"<br />
WirelessModeAuto = "Auto"</span></div>
<br />
<span style="font-size: large;"><b><span style="font-family: inherit;">Step 4: Enter these</span> in the registry in the right place - good luck with that</b></span><br />
<br />
To find where, I did a search for "Adhoc 11n" in regedit.exe. This is one of the settings you can choose for your drivers and it seemed unique enough. I only found two cases of this in my registry so I decided to add the above keys and values next to the Adhoc 11n. One of these had to be the correct settings for my device. Lucky for me the first one I chose happened to be the right one.<br />
<br />
This is how your registry should look. (Yeah you can't see the Adhoc 11n, but it's within the htAdhocEnable)<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisJ142-BnJp1W339N-DvOu7-oh_Ct63uRkF4qkoJSmWhGEGnRT4Tkr9n5Idb7p1r-O4CifBfOS1uszrjM1hx0TVNYzlfwvkKUC1wtHQX4c9mSjyjYAetJ3cvqHiA4JS_ArBlYDvLqUdgk7/s1600/atheros1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="404" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEisJ142-BnJp1W339N-DvOu7-oh_Ct63uRkF4qkoJSmWhGEGnRT4Tkr9n5Idb7p1r-O4CifBfOS1uszrjM1hx0TVNYzlfwvkKUC1wtHQX4c9mSjyjYAetJ3cvqHiA4JS_ArBlYDvLqUdgk7/s640/atheros1.png" width="640" /></a></div>
<br />
Create a key called NetBand, and add each value as a string. You can compare the format to the shortPreamble above it which is a setting that was installed by the driver. (If you don't trust me look at the .inf file from atheros.cz)<br />
<br />
Next create a sub key within NetBand called enum. This is where you get to choose Auto or Wireless b/g<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQYRpL2rKerV4OZ36Ku6n2Ht6T3Z_8cXYtyVQyAlzpR9VYhGlSAiUQK6c0JKdjCJyOg6oY5xO8iqfpaXrrIaM8GYruWR_bn1Z2ctUZjI_ctct8fgdEGrmn7f2eAfdOx5Fd2xO4UAavvmyE/s1600/atheros2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="401" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgQYRpL2rKerV4OZ36Ku6n2Ht6T3Z_8cXYtyVQyAlzpR9VYhGlSAiUQK6c0JKdjCJyOg6oY5xO8iqfpaXrrIaM8GYruWR_bn1Z2ctUZjI_ctct8fgdEGrmn7f2eAfdOx5Fd2xO4UAavvmyE/s640/atheros2.png" width="640" /></a></div>
<br />
After doing this, go to your wireless network card, click properties, configure, advanced and you should now be able to choose b/g or auto. <br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizQRZbpI2u6Nspv1RP1Wn18MPyUCeRPBarCMNNU1e3g34afjvKVolKs7rFlHhU3ChZ2UgbCjXC-BHxPLMS4LBkl-s9xQcXPp68l7o4DJ0fMleaWfj1MnPigrJTvZQkvQBAhHclYafe5uSb/s1600/atheros3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEizQRZbpI2u6Nspv1RP1Wn18MPyUCeRPBarCMNNU1e3g34afjvKVolKs7rFlHhU3ChZ2UgbCjXC-BHxPLMS4LBkl-s9xQcXPp68l7o4DJ0fMleaWfj1MnPigrJTvZQkvQBAhHclYafe5uSb/s1600/atheros3.png" /></a></div>
<br />
<br />
Set it to 802.11 b/g and hit OK. Your wireless connection will restart and hopefully you will now be able to connect. It did for me. Woot!<br />
<br />
<i>NOTE: For those who have a little more time and effort, or maybe someone at HP can figure this out - change the .inf file and add above registry fields so we can configure the Wireless Mode. This would save a lot of people time and effort.</i>bunwichhttp://www.blogger.com/profile/02484589527149322731noreply@blogger.com2